Automattic /
jetpack
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | /* |
||
| 4 | * Display a list of recent posts from a WordPress.com or Jetpack-enabled blog. |
||
| 5 | */ |
||
| 6 | |||
| 7 | class Jetpack_Display_Posts_Widget extends Jetpack_Display_Posts_Widget__Base { |
||
| 8 | /** |
||
| 9 | * @var string Widget options key prefix. |
||
| 10 | */ |
||
| 11 | public $widget_options_key_prefix = 'display_posts_site_data_'; |
||
| 12 | |||
| 13 | /** |
||
| 14 | * @var string The name of the cron that will update widget data. |
||
| 15 | */ |
||
| 16 | public static $cron_name = 'jetpack_display_posts_widget_cron_update'; |
||
| 17 | |||
| 18 | |||
| 19 | // DATA STORE |
||
| 20 | |||
| 21 | /** |
||
| 22 | * Gets blog data from the cache. |
||
| 23 | * |
||
| 24 | * @param string $site |
||
| 25 | * |
||
| 26 | * @return array|WP_Error |
||
| 27 | */ |
||
| 28 | public function get_blog_data( $site ) { |
||
| 29 | // load from cache, if nothing return an error |
||
| 30 | $site_hash = $this->get_site_hash( $site ); |
||
| 31 | |||
| 32 | $cached_data = $this->wp_get_option( $this->widget_options_key_prefix . $site_hash ); |
||
| 33 | |||
| 34 | /** |
||
| 35 | * If the cache is empty, return an empty_cache error. |
||
| 36 | */ |
||
| 37 | if ( false === $cached_data ) { |
||
| 38 | return new WP_Error( |
||
| 39 | 'empty_cache', |
||
|
0 ignored issues
–
show
|
|||
| 40 | __( 'Information about this blog is currently being retrieved.', 'jetpack' ) |
||
| 41 | ); |
||
| 42 | } |
||
| 43 | |||
| 44 | return $cached_data; |
||
| 45 | |||
| 46 | } |
||
| 47 | |||
| 48 | /** |
||
| 49 | * Update a widget instance. |
||
| 50 | * |
||
| 51 | * @param string $site The site to fetch the latest data for. |
||
| 52 | * |
||
| 53 | * @return array - the new data |
||
| 54 | */ |
||
| 55 | public function update_instance( $site ) { |
||
| 56 | |||
| 57 | /** |
||
| 58 | * Fetch current information for a site. |
||
| 59 | */ |
||
| 60 | $site_hash = $this->get_site_hash( $site ); |
||
| 61 | |||
| 62 | $option_key = $this->widget_options_key_prefix . $site_hash; |
||
| 63 | |||
| 64 | $instance_data = $this->wp_get_option( $option_key ); |
||
| 65 | |||
| 66 | /** |
||
| 67 | * Fetch blog data and save it in $instance_data. |
||
| 68 | */ |
||
| 69 | $new_data = $this->fetch_blog_data( $site, $instance_data ); |
||
| 70 | |||
| 71 | /** |
||
| 72 | * If the option doesn't exist yet - create a new option |
||
| 73 | */ |
||
| 74 | if ( false === $instance_data ) { |
||
| 75 | $this->wp_add_option( $option_key, $new_data ); |
||
| 76 | } |
||
| 77 | else { |
||
| 78 | $this->wp_update_option( $option_key, $new_data ); |
||
| 79 | } |
||
| 80 | |||
| 81 | return $new_data; |
||
| 82 | } |
||
| 83 | |||
| 84 | |||
| 85 | // WIDGET API |
||
| 86 | |||
| 87 | public function update( $new_instance, $old_instance ) { |
||
| 88 | $instance = parent::update( $new_instance, $old_instance ); |
||
| 89 | |||
| 90 | /** |
||
| 91 | * Forcefully activate the update cron when saving widget instance. |
||
| 92 | * |
||
| 93 | * So we can be sure that it will be running later. |
||
| 94 | */ |
||
| 95 | $this->activate_cron(); |
||
| 96 | |||
| 97 | return $instance; |
||
| 98 | } |
||
| 99 | |||
| 100 | |||
| 101 | // CRON |
||
| 102 | |||
| 103 | /** |
||
| 104 | * Activates widget update cron task. |
||
| 105 | */ |
||
| 106 | public static function activate_cron() { |
||
| 107 | if ( ! wp_next_scheduled( self::$cron_name ) ) { |
||
| 108 | wp_schedule_event( time(), 'minutes_10', self::$cron_name ); |
||
| 109 | } |
||
| 110 | } |
||
| 111 | |||
| 112 | /** |
||
| 113 | * Deactivates widget update cron task. |
||
| 114 | * |
||
| 115 | * This is a wrapper over the static method as it provides some syntactic sugar. |
||
| 116 | */ |
||
| 117 | public function deactivate_cron() { |
||
| 118 | self::deactivate_cron_static(); |
||
| 119 | } |
||
| 120 | |||
| 121 | /** |
||
| 122 | * Deactivates widget update cron task. |
||
| 123 | */ |
||
| 124 | public static function deactivate_cron_static() { |
||
| 125 | $next_scheduled_time = wp_next_scheduled( self::$cron_name ); |
||
| 126 | wp_unschedule_event( $next_scheduled_time, self::$cron_name ); |
||
| 127 | } |
||
| 128 | |||
| 129 | /** |
||
| 130 | * Checks if the update cron should be running and returns appropriate result. |
||
| 131 | * |
||
| 132 | * @return bool If the cron should be running or not. |
||
| 133 | */ |
||
| 134 | public function should_cron_be_running() { |
||
| 135 | /** |
||
| 136 | * The cron doesn't need to run empty loops. |
||
| 137 | */ |
||
| 138 | $widget_instances = $this->get_instances_sites(); |
||
| 139 | |||
| 140 | if ( empty( $widget_instances ) || ! is_array( $widget_instances ) ) { |
||
| 141 | return false; |
||
| 142 | } |
||
| 143 | |||
| 144 | if ( ! defined( 'IS_WPCOM' ) || ! IS_WPCOM ) { |
||
| 145 | /** |
||
| 146 | * If Jetpack is not active or in development mode, we don't want to update widget data. |
||
| 147 | */ |
||
| 148 | if ( ! Jetpack::is_active() && ! Jetpack::is_development_mode() ) { |
||
| 149 | return false; |
||
| 150 | } |
||
| 151 | |||
| 152 | /** |
||
| 153 | * If Extra Sidebar Widgets module is not active, we don't need to update widget data. |
||
| 154 | */ |
||
| 155 | if ( ! Jetpack::is_module_active( 'widgets' ) ) { |
||
| 156 | return false; |
||
| 157 | } |
||
| 158 | } |
||
| 159 | |||
| 160 | /** |
||
| 161 | * If none of the above checks failed, then we definitely want to update widget data. |
||
| 162 | */ |
||
| 163 | return true; |
||
| 164 | } |
||
| 165 | |||
| 166 | /** |
||
| 167 | * Main cron code. Updates all instances of the widget. |
||
| 168 | * |
||
| 169 | * @return bool |
||
| 170 | */ |
||
| 171 | public function cron_task() { |
||
| 172 | |||
| 173 | /** |
||
| 174 | * If the cron should not be running, disable it. |
||
| 175 | */ |
||
| 176 | if ( false === $this->should_cron_be_running() ) { |
||
| 177 | return true; |
||
| 178 | } |
||
| 179 | |||
| 180 | $instances_to_update = $this->get_instances_sites(); |
||
| 181 | |||
| 182 | /** |
||
| 183 | * If no instances are found to be updated - stop. |
||
| 184 | */ |
||
| 185 | if ( empty( $instances_to_update ) || ! is_array( $instances_to_update ) ) { |
||
| 186 | return true; |
||
| 187 | } |
||
| 188 | |||
| 189 | foreach ( $instances_to_update as $site_url ) { |
||
| 190 | $this->update_instance( $site_url ); |
||
| 191 | } |
||
| 192 | |||
| 193 | return true; |
||
| 194 | } |
||
| 195 | |||
| 196 | /** |
||
| 197 | * Get a list of unique sites from all instances of the widget. |
||
| 198 | * |
||
| 199 | * @return array|bool |
||
| 200 | */ |
||
| 201 | public function get_instances_sites() { |
||
| 202 | |||
| 203 | $widget_settings = $this->wp_get_option( 'widget_jetpack_display_posts_widget' ); |
||
| 204 | |||
| 205 | /** |
||
| 206 | * If the widget still hasn't been added anywhere, the config will not be present. |
||
| 207 | * |
||
| 208 | * In such case we don't want to continue execution. |
||
| 209 | */ |
||
| 210 | if ( false === $widget_settings || ! is_array( $widget_settings ) ) { |
||
| 211 | return false; |
||
| 212 | } |
||
| 213 | |||
| 214 | $urls = array(); |
||
| 215 | |||
| 216 | foreach ( $widget_settings as $widget_instance_data ) { |
||
| 217 | if ( isset( $widget_instance_data['url'] ) && ! empty( $widget_instance_data['url'] ) ) { |
||
| 218 | $urls[] = $widget_instance_data['url']; |
||
| 219 | } |
||
| 220 | } |
||
| 221 | |||
| 222 | /** |
||
| 223 | * Make sure only unique URLs are returned. |
||
| 224 | */ |
||
| 225 | $urls = array_unique( $urls ); |
||
| 226 | |||
| 227 | return $urls; |
||
| 228 | |||
| 229 | } |
||
| 230 | |||
| 231 | |||
| 232 | // MOCKABLES |
||
| 233 | |||
| 234 | /** |
||
| 235 | * This is just to make method mocks in the unit tests easier. |
||
| 236 | * |
||
| 237 | * @param string $param Option key to get |
||
| 238 | * |
||
| 239 | * @return mixed |
||
| 240 | * |
||
| 241 | * @codeCoverageIgnore |
||
| 242 | */ |
||
| 243 | public function wp_get_option( $param ) { |
||
| 244 | return get_option( $param ); |
||
| 245 | } |
||
| 246 | |||
| 247 | /** |
||
| 248 | * This is just to make method mocks in the unit tests easier. |
||
| 249 | * |
||
| 250 | * @param string $option_name Option name to be added |
||
| 251 | * @param mixed $option_value Option value |
||
| 252 | * |
||
| 253 | * @return mixed |
||
| 254 | * |
||
| 255 | * @codeCoverageIgnore |
||
| 256 | */ |
||
| 257 | public function wp_add_option( $option_name, $option_value ) { |
||
| 258 | return add_option( $option_name, $option_value ); |
||
| 259 | } |
||
| 260 | |||
| 261 | /** |
||
| 262 | * This is just to make method mocks in the unit tests easier. |
||
| 263 | * |
||
| 264 | * @param string $option_name Option name to be updated |
||
| 265 | * @param mixed $option_value Option value |
||
| 266 | * |
||
| 267 | * @return mixed |
||
| 268 | * |
||
| 269 | * @codeCoverageIgnore |
||
| 270 | */ |
||
| 271 | public function wp_update_option( $option_name, $option_value ) { |
||
| 272 | return update_option( $option_name, $option_value ); |
||
| 273 | } |
||
| 274 | } |
||
| 275 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignorePhpDoc annotation to the duplicate definition and it will be ignored.