~ubuntu-branches/debian/jessie/wordpress/jessie

« back to all changes in this revision

Viewing changes to wp-admin/includes/class-wp-upgrader.php

  • Committer: Package Import Robot
  • Author(s): Craig Small
  • Date: 2014-04-17 20:56:19 UTC
  • mfrom: (1.2.35)
  • Revision ID: package-import@ubuntu.com-20140417205619-nurbet6eho4yvwfv
Tags: 3.9+dfsg-1
* New upstream release
* 3.9 seems to handle different locations for plugins so the
  plugin directory handling patches have been cut back.

Show diffs side-by-side

added added

removed removed

Lines of Context:
113
113
                 *
114
114
                 * @since 3.7.0
115
115
                 *
116
 
                 * @param bool    $reply   Whether to bail without returning the package. Default is false.
117
 
                 * @param string  $package The package file name.
118
 
                 * @param object  $this    The WP_Upgrader instance.
 
116
                 * @param bool        $reply   Whether to bail without returning the package.
 
117
                 *                             Default false.
 
118
                 * @param string      $package The package file name.
 
119
                 * @param WP_Upgrader $this    The WP_Upgrader instance.
119
120
                 */
120
121
                $reply = apply_filters( 'upgrader_pre_download', false, $package, $this );
121
122
                if ( false !== $reply )
198
199
 
199
200
                $this->skin->feedback('installing_package');
200
201
 
201
 
                $res = apply_filters('upgrader_pre_install', true, $hook_extra);
 
202
                /**
 
203
                 * Filter the install response before the installation has started.
 
204
                 *
 
205
                 * Returning a truthy value, or one that could be evaluated as a WP_Error
 
206
                 * will effectively short-circuit the installation, returning that value
 
207
                 * instead.
 
208
                 *
 
209
                 * @since 2.8.0
 
210
                 *
 
211
                 * @param bool|WP_Error $response   Response.
 
212
                 * @param array         $hook_extra Extra arguments passed to hooked filters.
 
213
                 */
 
214
                $res = apply_filters( 'upgrader_pre_install', true, $hook_extra );
202
215
                if ( is_wp_error($res) )
203
216
                        return $res;
204
217
 
217
230
                else //It's only a single file, the upgrader will use the foldername of this file as the destination folder. foldername is based on zip filename.
218
231
                        $source = trailingslashit($source);
219
232
 
220
 
                //Hook ability to change the source file location..
221
 
                $source = apply_filters('upgrader_source_selection', $source, $remote_source, $this);
 
233
                /**
 
234
                 * Filter the source file location for the upgrade package.
 
235
                 *
 
236
                 * @since 2.8.0
 
237
                 *
 
238
                 * @param string      $source        File source location.
 
239
                 * @param string      $remote_source Remove file source location.
 
240
                 * @param WP_Upgrader $this          WP_Upgrader instance.
 
241
                 */
 
242
                $source = apply_filters( 'upgrader_source_selection', $source, $remote_source, $this );
222
243
                if ( is_wp_error($source) )
223
244
                        return $source;
224
245
 
243
264
                        $removed = true;
244
265
                        if ( $wp_filesystem->exists($remote_destination) )
245
266
                                $removed = $wp_filesystem->delete($remote_destination, true);
246
 
                        $removed = apply_filters('upgrader_clear_destination', $removed, $local_destination, $remote_destination, $hook_extra);
 
267
 
 
268
                        /**
 
269
                         * Filter whether the upgrader cleared the destination.
 
270
                         *
 
271
                         * @since 2.8.0
 
272
                         *
 
273
                         * @param bool   $removed            Whether the destination was cleared.
 
274
                         * @param string $local_destination  The local package destination.
 
275
                         * @param string $remote_destination The remote package destination.
 
276
                         * @param array  $hook_extra         Extra arguments passed to hooked filters.
 
277
                         */
 
278
                        $removed = apply_filters( 'upgrader_clear_destination', $removed, $local_destination, $remote_destination, $hook_extra );
247
279
 
248
280
                        if ( is_wp_error($removed) )
249
281
                                return $removed;
282
314
 
283
315
                $this->result = compact('local_source', 'source', 'source_name', 'source_files', 'destination', 'destination_name', 'local_destination', 'remote_destination', 'clear_destination', 'delete_source_dir');
284
316
 
285
 
                $res = apply_filters('upgrader_post_install', true, $hook_extra, $this->result);
 
317
                /**
 
318
                 * Filter the install response after the installation has finished.
 
319
                 *
 
320
                 * @since 2.8.0
 
321
                 *
 
322
                 * @param bool  $response   Install response.
 
323
                 * @param array $hook_extra Extra arguments passed to hooked filters.
 
324
                 * @param array $result     Installation result data.
 
325
                 */
 
326
                $res = apply_filters( 'upgrader_post_install', true, $hook_extra, $this->result );
 
327
 
286
328
                if ( is_wp_error($res) ) {
287
329
                        $this->result = $res;
288
330
                        return $res;
373
415
                $this->skin->after();
374
416
 
375
417
                if ( ! $is_multi ) {
 
418
 
 
419
                        /** This action is documented in wp-admin/includes/class-wp-upgrader.php */
376
420
                        do_action( 'upgrader_process_complete', $this, $hook_extra );
377
421
                        $this->skin->footer();
378
422
                }
560
604
                        $this->skin->plugin_info = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin, false, true);
561
605
 
562
606
                        if ( !isset( $current->response[ $plugin ] ) ) {
563
 
                                $this->skin->set_result(true);
 
607
                                $this->skin->set_result('up_to_date');
564
608
                                $this->skin->before();
565
609
                                $this->skin->feedback('up_to_date');
566
610
                                $this->skin->after();
593
637
 
594
638
                $this->maintenance_mode(false);
595
639
 
 
640
                /**
 
641
                 * Fires when the bulk upgrader process is complete.
 
642
                 *
 
643
                 * @since 3.6.0
 
644
                 *
 
645
                 * @param Plugin_Upgrader $this Plugin_Upgrader instance. In other contexts, $this, might
 
646
                 *                              be a Theme_Upgrader or Core_Upgrade instance.
 
647
                 * @param array           $data {
 
648
                 *     Array of bulk item update data.
 
649
                 *
 
650
                 *     @type string $action   Type of action. Default 'update'.
 
651
                 *     @type string $type     Type of update process. Accepts 'plugin', 'theme', or 'core'.
 
652
                 *     @type bool   $bulk     Whether the update process is a bulk update. Default true.
 
653
                 *     @type array  $packages Array of plugin, theme, or core packages to update.
 
654
                 * }
 
655
                 */
596
656
                do_action( 'upgrader_process_complete', $this, array(
597
657
                        'action' => 'update',
598
658
                        'type' => 'plugin',
863
923
                if ( !isset( $current->response[ $theme ] ) ) {
864
924
                        $this->skin->before();
865
925
                        $this->skin->set_result(false);
866
 
                        $this->skin->error('up_to_date');
 
926
                        $this->skin->error( 'up_to_date' );
867
927
                        $this->skin->after();
868
928
                        return false;
869
929
                }
948
1008
                        if ( !isset( $current->response[ $theme ] ) ) {
949
1009
                                $this->skin->set_result(true);
950
1010
                                $this->skin->before();
951
 
                                $this->skin->feedback('up_to_date');
 
1011
                                $this->skin->feedback( 'up_to_date' );
952
1012
                                $this->skin->after();
953
1013
                                $results[$theme] = true;
954
1014
                                continue;
976
1036
 
977
1037
                $this->maintenance_mode(false);
978
1038
 
 
1039
                /** This action is documented in wp-admin/includes/class-wp-upgrader.php */
979
1040
                do_action( 'upgrader_process_complete', $this, array(
980
1041
                        'action' => 'update',
981
1042
                        'type' => 'theme',
1346
1407
                elseif ( $parsed_args['pre_check_md5'] && ! $this->check_files() )
1347
1408
                        $partial = false;
1348
1409
 
1349
 
                // If partial update is returned from the API, use that, unless we're doing a reinstall.
1350
 
                // If we cross the new_bundled version number, then use the new_bundled zip.
1351
 
                // Don't though if the constant is set to skip bundled items.
1352
 
                // If the API returns a no_content zip, go with it. Finally, default to the full zip.
 
1410
                /*
 
1411
                 * If partial update is returned from the API, use that, unless we're doing
 
1412
                 * a reinstall. If we cross the new_bundled version number, then use
 
1413
                 * the new_bundled zip. Don't though if the constant is set to skip bundled items.
 
1414
                 * If the API returns a no_content zip, go with it. Finally, default to the full zip.
 
1415
                 */
1353
1416
                if ( $parsed_args['do_rollback'] && $current->packages->rollback )
1354
1417
                        $to_download = 'rollback';
1355
1418
                elseif ( $current->packages->partial && 'reinstall' != $current->response && $wp_version == $current->partial_version && $partial )
1401
1464
                        }
1402
1465
 
1403
1466
                        if ( $try_rollback ) {
 
1467
                                /** This filter is documented in wp-admin/includes/update-core.php */
1404
1468
                                apply_filters( 'update_feedback', $result );
 
1469
 
 
1470
                                /** This filter is documented in wp-admin/includes/update-core.php */
1405
1471
                                apply_filters( 'update_feedback', $this->strings['start_rollback'] );
1406
1472
 
1407
1473
                                $rollback_result = $this->upgrade( $current, array_merge( $parsed_args, array( 'do_rollback' => true ) ) );
1411
1477
                        }
1412
1478
                }
1413
1479
 
 
1480
                /** This action is documented in wp-admin/includes/class-wp-upgrader.php */
1414
1481
                do_action( 'upgrader_process_complete', $this, array( 'action' => 'update', 'type' => 'core' ) );
1415
1482
 
1416
1483
                // Clear the current updates
1506
1573
 
1507
1574
                // 3: 3.7-alpha-25000 -> 3.7-alpha-25678 -> 3.7-beta1 -> 3.7-beta2
1508
1575
                if ( $current_is_development_version ) {
 
1576
 
 
1577
                        /**
 
1578
                         * Filter whether to enable automatic core updates for development versions.
 
1579
                         *
 
1580
                         * @since 3.7.0
 
1581
                         *
 
1582
                         * @param bool $upgrade_dev Whether to enable automatic updates for
 
1583
                         *                          development versions.
 
1584
                         */
1509
1585
                        if ( ! apply_filters( 'allow_dev_auto_core_updates', $upgrade_dev ) )
1510
1586
                                return false;
1511
1587
                        // else fall through to minor + major branches below
1512
1588
                }
1513
1589
 
1514
1590
                // 4: Minor In-branch updates (3.7.0 -> 3.7.1 -> 3.7.2 -> 3.7.4)
1515
 
                if ( $current_branch == $new_branch )
 
1591
                if ( $current_branch == $new_branch ) {
 
1592
 
 
1593
                        /**
 
1594
                         * Filter whether to enable minor automatic core updates.
 
1595
                         *
 
1596
                         * @since 3.7.0
 
1597
                         *
 
1598
                         * @param bool $upgrade_minor Whether to enable minor automatic core updates.
 
1599
                         */
1516
1600
                        return apply_filters( 'allow_minor_auto_core_updates', $upgrade_minor );
 
1601
                }
1517
1602
 
1518
1603
                // 5: Major version updates (3.7.0 -> 3.8.0 -> 3.9.1)
1519
 
                if ( version_compare( $new_branch, $current_branch, '>' ) )
 
1604
                if ( version_compare( $new_branch, $current_branch, '>' ) ) {
 
1605
 
 
1606
                        /**
 
1607
                         * Filter whether to enable major automatic core updates.
 
1608
                         *
 
1609
                         * @since 3.7.0
 
1610
                         *
 
1611
                         * @param bool $upgrade_major Whether to enable major automatic core updates.
 
1612
                         */
1520
1613
                        return apply_filters( 'allow_major_auto_core_updates', $upgrade_major );
 
1614
                }
1521
1615
 
1522
1616
                // If we're not sure, we don't want it
1523
1617
                return false;
1658
1752
                 * This also disables update notification emails. That may change in the future.
1659
1753
                 *
1660
1754
                 * @since 3.7.0
 
1755
                 *
1661
1756
                 * @param bool $disabled Whether the updater should be disabled.
1662
1757
                 */
1663
1758
                return apply_filters( 'automatic_updater_disabled', $disabled );
1711
1806
                }
1712
1807
 
1713
1808
                /**
1714
 
                 * Filter whether the automatic updater should consider a filesystem location to be potentially
1715
 
                 * managed by a version control system.
 
1809
                 * Filter whether the automatic updater should consider a filesystem
 
1810
                 * location to be potentially managed by a version control system.
1716
1811
                 *
1717
1812
                 * @since 3.7.0
1718
1813
                 *
1719
 
                 * @param bool $checkout  Whether a VCS checkout was discovered at $context or ABSPATH, or anywhere higher.
1720
 
                 * @param string $context The filesystem context (a path) against which filesystem status should be checked.
 
1814
                 * @param bool $checkout  Whether a VCS checkout was discovered at $context
 
1815
                 *                        or ABSPATH, or anywhere higher.
 
1816
                 * @param string $context The filesystem context (a path) against which
 
1817
                 *                        filesystem status should be checked.
1721
1818
                 */
1722
1819
                return apply_filters( 'automatic_updates_is_vcs_checkout', $checkout, $context );
1723
1820
        }
1727
1824
         *
1728
1825
         * @since 3.7.0
1729
1826
         *
1730
 
         * @param string $type    The type of update being checked: 'core', 'theme', 'plugin', 'translation'.
 
1827
         * @param string $type    The type of update being checked: 'core', 'theme',
 
1828
         *                        'plugin', 'translation'.
1731
1829
         * @param object $item    The update offer.
1732
 
         * @param string $context The filesystem context (a path) against which filesystem access and status
1733
 
         *                        should be checked.
 
1830
         * @param string $context The filesystem context (a path) against which filesystem
 
1831
         *                        access and status should be checked.
1734
1832
         */
1735
1833
        public function should_update( $type, $item, $context ) {
1736
1834
                // Used to see if WP_Filesystem is set up to allow unattended updates.
1758
1856
                 * The dynamic portion of the hook name, $type, refers to the type of update
1759
1857
                 * being checked. Can be 'core', 'theme', 'plugin', or 'translation'.
1760
1858
                 *
1761
 
                 * Generally speaking, plugins, themes, and major core versions are not updated by default,
1762
 
                 * while translations and minor and development versions for core are updated by default.
 
1859
                 * Generally speaking, plugins, themes, and major core versions are not updated
 
1860
                 * by default, while translations and minor and development versions for core
 
1861
                 * are updated by default.
1763
1862
                 *
1764
 
                 * See the filters allow_dev_auto_core_updates, allow_minor_auto_core_updates, and
1765
 
                 * allow_major_auto_core_updates more straightforward filters to adjust core updates.
 
1863
                 * See the allow_dev_auto_core_updates, allow_minor_auto_core_updates, and
 
1864
                 * allow_major_auto_core_updates filters for a more straightforward way to
 
1865
                 * adjust core updates.
1766
1866
                 *
1767
1867
                 * @since 3.7.0
1768
1868
                 *
1813
1913
                $notify = ! empty( $item->notify_email );
1814
1914
 
1815
1915
                /**
1816
 
                 * Whether to notify the site administrator of a new core update.
1817
 
                 *
1818
 
                 * By default, administrators are notified when the update offer received from WordPress.org
1819
 
                 * sets a particular flag. This allows for discretion in if and when to notify.
1820
 
                 *
1821
 
                 * This filter only fires once per release -- if the same email address was already
1822
 
                 * notified of the same new version, we won't repeatedly email the administrator.
1823
 
                 *
1824
 
                 * This filter is also used on about.php to check if a plugin has disabled these notifications.
 
1916
                 * Filter whether to notify the site administrator of a new core update.
 
1917
                 *
 
1918
                 * By default, administrators are notified when the update offer received
 
1919
                 * from WordPress.org sets a particular flag. This allows some discretion
 
1920
                 * in if and when to notify.
 
1921
                 *
 
1922
                 * This filter is only evaluated once per release. If the same email address
 
1923
                 * was already notified of the same new version, WordPress won't repeatedly
 
1924
                 * email the administrator.
 
1925
                 *
 
1926
                 * This filter is also used on about.php to check if a plugin has disabled
 
1927
                 * these notifications.
1825
1928
                 *
1826
1929
                 * @since 3.7.0
1827
1930
                 *
1828
 
                 * @param bool $notify Whether the site administrator is notified.
1829
 
                 * @param object $item The update offer.
 
1931
                 * @param bool   $notify Whether the site administrator is notified.
 
1932
                 * @param object $item   The update offer.
1830
1933
                 */
1831
1934
                if ( ! apply_filters( 'send_core_update_notification_email', $notify, $item ) )
1832
1935
                        return false;
1859
1962
                                break;
1860
1963
                        case 'theme':
1861
1964
                                $upgrader = new Theme_Upgrader( $skin );
1862
 
                                $context  = get_theme_root( $item );
 
1965
                                $context  = get_theme_root( $item->theme );
1863
1966
                                break;
1864
1967
                        case 'translation':
1865
1968
                                $upgrader = new Language_Pack_Upgrader( $skin );
2034
2137
                // Send debugging email to all development installs.
2035
2138
                if ( ! empty( $this->update_results ) ) {
2036
2139
                        $development_version = false !== strpos( $wp_version, '-' );
 
2140
 
2037
2141
                        /**
2038
2142
                         * Filter whether to send a debugging email for each automatic background update.
2039
2143
                         *
2040
2144
                         * @since 3.7.0
2041
 
                         * @param bool $development_version By default, emails are sent if the install is a development version.
 
2145
                         *
 
2146
                         * @param bool $development_version By default, emails are sent if the
 
2147
                         *                                  install is a development version.
2042
2148
                         *                                  Return false to avoid the email.
2043
2149
                         */
2044
2150
                        if ( apply_filters( 'automatic_updates_send_debug_email', $development_version ) )
2048
2154
                                $this->after_core_update( $this->update_results['core'][0] );
2049
2155
 
2050
2156
                        /**
2051
 
                         * Action triggered after all automatic updates have run.
2052
 
                         *
2053
 
                         * @since 3.8.0
2054
 
                         *
2055
 
                         * @param array $update_results The results of all attempted updates.
2056
 
                         */
 
2157
                         * Fires after all automatic updates have run.
 
2158
                         *
 
2159
                         * @since 3.8.0
 
2160
                         *
 
2161
                         * @param array $update_results The results of all attempted updates.
 
2162
                         */
2057
2163
                        do_action( 'automatic_updates_complete', $this->update_results );
2058
2164
                }
2059
2165
 
2176
2282
                 * @since 3.7.0
2177
2283
                 *
2178
2284
                 * @param bool   $send        Whether to send the email. Default true.
2179
 
                 * @param string $type        The type of email to send. Can be one of 'success', 'fail', 'critical'.
 
2285
                 * @param string $type        The type of email to send. Can be one of
 
2286
                 *                            'success', 'fail', 'critical'.
2180
2287
                 * @param object $core_update The update offer that was attempted.
2181
2288
                 * @param mixed  $result      The result for the core update. Can be WP_Error.
2182
2289
                 */
2258
2365
                                break;
2259
2366
                }
2260
2367
 
 
2368
                $critical_support = 'critical' === $type && ! empty( $core_update->support_email );
 
2369
                if ( $critical_support ) {
 
2370
                        // Support offer if available.
 
2371
                        $body .= "\n\n" . sprintf( __( "The WordPress team is willing to help you. Forward this email to %s and the team will work with you to make sure your site is working." ), $core_update->support_email );
 
2372
                } else {
 
2373
                        // Add a note about the support forums.
 
2374
                        $body .= "\n\n" . __( 'If you experience any issues or need support, the volunteers in the WordPress.org support forums may be able to help.' );
 
2375
                        $body .= "\n" . __( 'https://wordpress.org/support/' );
 
2376
                }
 
2377
 
2261
2378
                // Updates are important!
2262
 
                if ( $type != 'success' || $newer_version_available )
 
2379
                if ( $type != 'success' || $newer_version_available ) {
2263
2380
                        $body .= "\n\n" . __( 'Keeping your site updated is important for security. It also makes the internet a safer place for you and your readers.' );
 
2381
                }
2264
2382
 
2265
 
                // Add a note about the support forums to all emails.
2266
 
                $body .= "\n\n" . __( 'If you experience any issues or need support, the volunteers in the WordPress.org support forums may be able to help.' );
2267
 
                $body .= "\n" . __( 'http://wordpress.org/support/' );
 
2383
                if ( $critical_support ) {
 
2384
                        $body .= " " . __( "If you reach out to us, we'll also ensure you'll never have this problem again." );
 
2385
                }
2268
2386
 
2269
2387
                // If things are successful and we're now on the latest, mention plugins and themes if any are out of date.
2270
2388
                if ( $type == 'success' && ! $newer_version_available && ( get_plugin_updates() || get_theme_updates() ) ) {
2307
2425
                $headers = '';
2308
2426
 
2309
2427
                $email = compact( 'to', 'subject', 'body', 'headers' );
 
2428
 
2310
2429
                /**
2311
2430
                 * Filter the email sent following an automatic background core update.
2312
2431
                 *
2315
2434
                 * @param array $email {
2316
2435
                 *     Array of email arguments that will be passed to wp_mail().
2317
2436
                 *
2318
 
                 *     @type string $to      The email recipient. An array of emails can be returned, as handled by wp_mail().
 
2437
                 *     @type string $to      The email recipient. An array of emails
 
2438
                 *                            can be returned, as handled by wp_mail().
2319
2439
                 *     @type string $subject The email's subject.
2320
2440
                 *     @type string $body    The email message body.
2321
2441
                 *     @type string $headers Any email headers, defaults to no headers.
2322
2442
                 * }
2323
 
                 * @param string $type        The type of email being sent. Can be one of 'success', 'fail', 'manual', 'critical'.
 
2443
                 * @param string $type        The type of email being sent. Can be one of
 
2444
                 *                            'success', 'fail', 'manual', 'critical'.
2324
2445
                 * @param object $core_update The update offer that was attempted.
2325
2446
                 * @param mixed  $result      The result for the core update. Can be WP_Error.
2326
2447
                 */
2327
2448
                $email = apply_filters( 'auto_core_update_email', $email, $type, $core_update, $result );
2328
2449
 
2329
 
                wp_mail( $email['to'], $email['subject'], $email['body'], $email['headers'] );
 
2450
                wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );
2330
2451
        }
2331
2452
 
2332
2453
        /**
2401
2522
This debugging email is sent when you are using a development version of WordPress.
2402
2523
 
2403
2524
If you think these failures might be due to a bug in WordPress, could you report it?
2404
 
 * Open a thread in the support forums: http://wordpress.org/support/forum/alphabeta
 
2525
 * Open a thread in the support forums: https://wordpress.org/support/forum/alphabeta
2405
2526
 * Or, if you're comfortable writing a bug report: http://core.trac.wordpress.org/
2406
2527
 
2407
2528
Thanks! -- The WordPress Team" );
2411
2532
                        $subject = sprintf( __( '[%s] Background updates have finished' ), $site_title );
2412
2533
                }
2413
2534
 
2414
 
                $body[] = __( 'UPDATE LOG' );
2415
 
                $body[] = '==========';
 
2535
                $title = __( 'UPDATE LOG' );
 
2536
                $body[] = $title;
 
2537
                $body[] = str_repeat( '=', strlen( $title ) );
2416
2538
                $body[] = '';
2417
2539
 
2418
2540
                foreach ( array( 'core', 'plugin', 'theme', 'translation' ) as $type ) {
2456
2578
                );
2457
2579
 
2458
2580
                /**
2459
 
                 * Filter the debug email that can be sent following an automatic background core update.
 
2581
                 * Filter the debug email that can be sent following an automatic
 
2582
                 * background core update.
2460
2583
                 *
2461
2584
                 * @since 3.8.0
2462
2585
                 *
2463
2586
                 * @param array $email {
2464
2587
                 *     Array of email arguments that will be passed to wp_mail().
2465
2588
                 *
2466
 
                 *     @type string $to      The email recipient. An array of emails can be returned,
2467
 
                 *                           as handled by wp_mail().
 
2589
                 *     @type string $to      The email recipient. An array of emails
 
2590
                 *                           can be returned, as handled by wp_mail().
2468
2591
                 *     @type string $subject Email subject.
2469
2592
                 *     @type string $body    Email message body.
2470
2593
                 *     @type string $headers Any email headers. Default empty.
2474
2597
                 */
2475
2598
                $email = apply_filters( 'automatic_updates_debug_email', $email, $failures, $this->update_results );
2476
2599
 
2477
 
                wp_mail( $email['to'], $email['subject'], $email['body'], $email['headers'] );
 
2600
                wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );
2478
2601
        }
2479
2602
}