| | 1 | <?php |
| | 2 | |
| | 3 | if ( $_SERVER['SCRIPT_FILENAME'] == __FILE__ ) |
| | 4 | die( 'Access denied.' ); |
| | 5 | |
| | 6 | if ( ! class_exists( 'TGGRSourceGoogle' ) ) { |
| | 7 | /** |
| | 8 | * Creates a custom post type and associated taxonomies |
| | 9 | * @package Tagregator |
| | 10 | */ |
| | 11 | class TGGRSourceGoogle extends TGGRMediaSource { |
| | 12 | protected static $readable_properties = array( 'view_folder' ); |
| | 13 | protected static $writeable_properties = array(); |
| | 14 | protected $setting_names, $default_settings, $view_folder; |
| | 15 | |
| | 16 | const POST_TYPE_NAME_SINGULAR = 'Google+ Activity'; |
| | 17 | const POST_TYPE_NAME_PLURAL = 'Google+ Activities'; |
| | 18 | const POST_TYPE_SLUG = 'tggr-google'; |
| | 19 | const SETTINGS_TITLE = 'Google+'; |
| | 20 | const SETTINGS_PREFIX = 'tggr_google_'; |
| | 21 | const API_URL = 'https://www.googleapis.com/plus'; // It's important to use HTTPS for security |
| | 22 | |
| | 23 | /** |
| | 24 | * Constructor |
| | 25 | * @mvc Controller |
| | 26 | */ |
| | 27 | protected function __construct() { |
| | 28 | $this->view_folder = dirname( __DIR__ ) . '/views/'. str_replace( '.php', '', basename( __FILE__ ) ); |
| | 29 | $this->setting_names = array( 'API Key' ); |
| | 30 | |
| | 31 | foreach ( $this->setting_names as $key ) { |
| | 32 | $this->default_settings[ strtolower( str_replace( ' ', '_', $key ) ) ] = ''; |
| | 33 | } |
| | 34 | $this->default_settings[ '_newest_activity_date' ] = 0; |
| | 35 | |
| | 36 | $this->register_hook_callbacks(); |
| | 37 | } |
| | 38 | |
| | 39 | /** |
| | 40 | * Prepares site to use the plugin during activation |
| | 41 | * @mvc Controller |
| | 42 | * |
| | 43 | * @param bool $network_wide |
| | 44 | */ |
| | 45 | public function activate( $network_wide ) { |
| | 46 | $this->init(); |
| | 47 | } |
| | 48 | |
| | 49 | /** |
| | 50 | * Rolls back activation procedures when de-activating the plugin |
| | 51 | * @mvc Controller |
| | 52 | */ |
| | 53 | public function deactivate() {} |
| | 54 | |
| | 55 | /** |
| | 56 | * Register callbacks for actions and filters |
| | 57 | * @mvc Controller |
| | 58 | */ |
| | 59 | public function register_hook_callbacks() { |
| | 60 | add_action( 'init', array( $this, 'init' ) ); |
| | 61 | add_action( 'admin_init', array( $this, 'register_settings' ) ); |
| | 62 | |
| | 63 | add_filter( Tagregator::PREFIX . 'default_settings', __CLASS__ . '::register_default_settings' ); |
| | 64 | } |
| | 65 | |
| | 66 | /** |
| | 67 | * Initializes variables |
| | 68 | * @mvc Controller |
| | 69 | */ |
| | 70 | public function init() { |
| | 71 | self::register_post_type( |
| | 72 | self::POST_TYPE_SLUG, |
| | 73 | $this->get_post_type_params( |
| | 74 | self::POST_TYPE_SLUG, |
| | 75 | self::POST_TYPE_NAME_SINGULAR, |
| | 76 | self::POST_TYPE_NAME_PLURAL |
| | 77 | ) |
| | 78 | ); |
| | 79 | self::create_post_author(); |
| | 80 | self::get_post_author_user_id(); |
| | 81 | } |
| | 82 | |
| | 83 | /** |
| | 84 | * Executes the logic of upgrading from specific older versions of the plugin to the current version |
| | 85 | * @mvc Model |
| | 86 | * |
| | 87 | * @param string $db_version |
| | 88 | */ |
| | 89 | public function upgrade( $db_version = 0 ) {} |
| | 90 | |
| | 91 | /** |
| | 92 | * Validates submitted setting values before they get saved to the database. |
| | 93 | * Invalid data will be overwritten with defaults. |
| | 94 | * @mvc Model |
| | 95 | * |
| | 96 | * @param array $new_settings |
| | 97 | * @return array |
| | 98 | */ |
| | 99 | public function validate_settings( $new_settings ) { |
| | 100 | $new_settings = shortcode_atts( $this->default_settings, $new_settings, TGGRSettings::SETTING_SLUG ); |
| | 101 | |
| | 102 | foreach ( $new_settings as $setting => $value ) { |
| | 103 | switch ( $setting ) { |
| | 104 | case '_newest_activity_date': |
| | 105 | $new_settings[ $setting ] = absint( $value ); |
| | 106 | break; |
| | 107 | default: |
| | 108 | $new_settings[ $setting ] = $this->default_settings[ $setting ]; |
| | 109 | if ( is_string( $value ) ) { |
| | 110 | $new_settings[ $setting ] = sanitize_text_field( $value ); |
| | 111 | } |
| | 112 | break; |
| | 113 | } |
| | 114 | } |
| | 115 | |
| | 116 | return $new_settings; |
| | 117 | } |
| | 118 | |
| | 119 | /** |
| | 120 | * Fetches new items from an external sources and saves them as posts in the local database |
| | 121 | * @mvc Controller |
| | 122 | * |
| | 123 | * @param string $hashtag |
| | 124 | */ |
| | 125 | public function import_new_items( $hashtag ) { |
| | 126 | $activities = self::get_new_activities( |
| | 127 | TGGRSettings::get_instance()->settings[ __CLASS__ ]['api_key'], |
| | 128 | $hashtag, |
| | 129 | TGGRSettings::get_instance()->settings[ __CLASS__ ]['_newest_activity_date'] |
| | 130 | ); |
| | 131 | |
| | 132 | $this->import_new_posts( $this->convert_items_to_posts( $activities, $hashtag ) ); |
| | 133 | self::update_newest_activity_date( $hashtag ); |
| | 134 | } |
| | 135 | |
| | 136 | /** |
| | 137 | * Retrieves activities containing the given hashtag that were posted since the last import |
| | 138 | * @mvc Model |
| | 139 | * |
| | 140 | * @param string $api_key |
| | 141 | * @param string $hashtag |
| | 142 | * @param string $last_updated_activities The timestamp of the most recent item that is already saved in the database |
| | 143 | * @return mixed string|false |
| | 144 | */ |
| | 145 | protected static function get_new_activities( $api_key, $hashtag, $last_updated_activities ) { |
| | 146 | $activities = false; |
| | 147 | |
| | 148 | if ( $api_key && $hashtag ) { |
| | 149 | $url = sprintf( |
| | 150 | '%s/v1/activities?query=%s&key=%s', |
| | 151 | self::API_URL, |
| | 152 | urlencode( $hashtag ), |
| | 153 | urlencode( $api_key ) |
| | 154 | ); |
| | 155 | |
| | 156 | $response = wp_remote_get( $url ); |
| | 157 | $response = json_decode( wp_remote_retrieve_body( $response ) ); |
| | 158 | |
| | 159 | if ( isset( $response->updated ) && strtotime( $response->updated ) > $last_updated_activities && ! empty( $response->items ) ) { |
| | 160 | $activities = $response->items; |
| | 161 | } |
| | 162 | } |
| | 163 | |
| | 164 | return $activities; |
| | 165 | } |
| | 166 | |
| | 167 | /** |
| | 168 | * Converts data from external source into a post/postmeta format so it can be saved in the local database |
| | 169 | * @mvc Model |
| | 170 | * |
| | 171 | * @param array $items |
| | 172 | * @param string $term |
| | 173 | * @return array |
| | 174 | */ |
| | 175 | public function convert_items_to_posts( $items, $term ) { |
| | 176 | $posts = array(); |
| | 177 | |
| | 178 | if ( $items ) { |
| | 179 | foreach ( $items as $item ) { |
| | 180 | $post_timestamp_gmt = strtotime( $item->published ); |
| | 181 | $post_timestamp_local = self::convert_gmt_timestamp_to_local( $post_timestamp_gmt ); |
| | 182 | |
| | 183 | $post = array( |
| | 184 | 'post_author' => TGGRMediaSource::$post_author_id, |
| | 185 | 'post_content' => wp_kses( $item->object->content, wp_kses_allowed_html( 'data' ), array( 'http', 'https', 'mailto' ) ), |
| | 186 | 'post_date' => date( 'Y-m-d H:i:s', $post_timestamp_local ), |
| | 187 | 'post_date_gmt' => date( 'Y-m-d H:i:s', $post_timestamp_gmt ), |
| | 188 | 'post_status' => 'publish', |
| | 189 | 'post_title' => sanitize_text_field( $item->title ), |
| | 190 | 'post_type' => self::POST_TYPE_SLUG, |
| | 191 | ); |
| | 192 | |
| | 193 | $post_meta = array( |
| | 194 | 'source_id' => sanitize_text_field( $item->id ), |
| | 195 | 'post_permalink' => esc_url_raw( $item->url ), |
| | 196 | 'author_id' => sanitize_text_field( $item->actor->id ), |
| | 197 | 'author_name' => sanitize_text_field( $item->actor->displayName ), |
| | 198 | 'author_url' => esc_url( $item->actor->url ), |
| | 199 | 'author_image_url' => esc_url( $item->actor->image->url ), |
| | 200 | 'media' => array( |
| | 201 | array( |
| | 202 | 'small_url' => isset( $item->object->attachments[0]->image ) ? esc_url_raw( $item->object->attachments[0]->image->url ) : false, |
| | 203 | 'large_url' => isset( $item->object->attachments[0]->fullImage ) ? esc_url_raw( $item->object->attachments[0]->fullImage->url ) : false, |
| | 204 | 'type' => 'image', |
| | 205 | ), |
| | 206 | ), |
| | 207 | ); |
| | 208 | |
| | 209 | $posts[] = array( |
| | 210 | 'post' => $post, |
| | 211 | 'post_meta' => $post_meta, |
| | 212 | 'term_name' => $term, |
| | 213 | ); |
| | 214 | } |
| | 215 | } |
| | 216 | |
| | 217 | return $posts; |
| | 218 | } |
| | 219 | |
| | 220 | /** |
| | 221 | * Updates the _newest_activity_date setting with the timestamp of the most recent |
| | 222 | * @mvc Model |
| | 223 | * |
| | 224 | * @param string $hashtag |
| | 225 | */ |
| | 226 | protected static function update_newest_activity_date( $hashtag ) { |
| | 227 | $latest_post = self::get_latest_hashtagged_post( self::POST_TYPE_SLUG, $hashtag ); |
| | 228 | |
| | 229 | if ( isset( $latest_post->ID ) ) { |
| | 230 | $settings = TGGRSettings::get_instance()->settings; |
| | 231 | $settings[ __CLASS__ ]['_newest_activity_date'] = strtotime( $latest_post->post_date_gmt . ' GMT' ); |
| | 232 | TGGRSettings::get_instance()->settings = $settings; |
| | 233 | } |
| | 234 | } |
| | 235 | |
| | 236 | /** |
| | 237 | * Gathers the data that the media-item view will need |
| | 238 | * @mvc Model |
| | 239 | * |
| | 240 | * @param int $post_id |
| | 241 | * @return array |
| | 242 | */ |
| | 243 | public function get_item_view_data( $post_id ) { |
| | 244 | $postmeta = get_post_custom( $post_id ); |
| | 245 | $necessary_data = array( |
| | 246 | 'source_id' => $postmeta['source_id'][0], |
| | 247 | 'post_permalink' => $postmeta['post_permalink'][0], |
| | 248 | 'author_name' => $postmeta['author_name'][0], |
| | 249 | 'author_url' => $postmeta['author_url'][0], |
| | 250 | 'author_image_url' => $postmeta['author_image_url'][0], |
| | 251 | 'media' => isset( $postmeta['media'][0] ) ? maybe_unserialize( $postmeta['media'][0] ) : array(), |
| | 252 | 'logo_url' => plugins_url( 'images/source-logos/googleplus.png', __DIR__ ), |
| | 253 | ); |
| | 254 | |
| | 255 | return $necessary_data; |
| | 256 | } |
| | 257 | } // end TGGRSourceGoogle |
| | 258 | } |
| | 259 | No newline at end of file |