WordPress.org

Making WordPress.org

Ticket #4875: 4875.2.diff

File 4875.2.diff, 19.9 KB (added by dingo_d, 2 years ago)

An updated patch for bulk suspension.

  • new file wordpress.org/public_html/wp-content/plugins/theme-directory/assets/suspend-form.css

    diff --git wordpress.org/public_html/wp-content/plugins/theme-directory/assets/suspend-form.css wordpress.org/public_html/wp-content/plugins/theme-directory/assets/suspend-form.css
    new file mode 100644
    index 000000000..c742b3f10
    - +  
     1.bulk-suspension-form {
     2  display: flex;
     3  margin-top: 20px;
     4}
     5
     6.fields-wrapper {
     7  background-color: #fff;
     8  width: 100%;
     9  border-radius: 10px;
     10  padding: 20px;
     11  border: 1px solid #7e8993;
     12}
     13
     14.fields-wrapper--metabox {
     15  width: auto;
     16  border: none;
     17  padding: 0;
     18}
     19
     20.fields-row {
     21  display: flex;
     22  flex-direction: row;
     23  flex-wrap: wrap;
     24  width: 100%;
     25  margin-bottom: 20px;
     26}
     27
     28.fields-column {
     29  display: flex;
     30  flex-direction: column;
     31  flex-basis: 100%;
     32  flex: 1;
     33  margin: 0 10px;
     34}
  • new file wordpress.org/public_html/wp-content/plugins/theme-directory/class-wporg-themes-suspended-packages.php

    diff --git wordpress.org/public_html/wp-content/plugins/theme-directory/class-wporg-themes-suspended-packages.php wordpress.org/public_html/wp-content/plugins/theme-directory/class-wporg-themes-suspended-packages.php
    new file mode 100644
    index 000000000..878adcf84
    - +  
     1<?php
     2
     3namespace WordPressdotorg\Theme_Directory;
     4
     5/**
     6 * Class that handles suspended themes
     7 *
     8 * Provides a way to see the suspended themes, reason why they were suspended, when they were suspended,
     9 * when does the suspension expires and who suspended them.
     10 */
     11class WPORG_Themes_Suspended_Packages {
     12        /**
     13         * Register all the hooks related to the new functionality
     14         */
     15        public function register() {
     16                add_action( 'admin_enqueue_scripts', [ $this, 'add_suspension_scripts' ] );
     17                add_filter( 'manage_repopackage_posts_columns', [ $this, 'add_new_post_columns' ] );
     18                add_action( 'manage_repopackage_posts_custom_column', [ $this, 'add_column_content' ], 10, 2 );
     19                add_filter( 'manage_edit-repopackage_sortable_columns', [ $this, 'make_columns_sortable' ] );
     20                add_filter( 'bulk_actions-edit-repopackage', [ $this, 'add_bulk_suspend_option' ] );
     21                add_filter( 'handle_bulk_actions-edit-repopackage', [ $this, 'suspend_bulk_action_handler' ], 10, 3 );
     22                add_action( 'admin_post_suspend_themes', [ $this, 'suspend_themes_action' ] );
     23                add_action( 'admin_post_nopriv_suspend_themes', [ $this, 'suspend_themes_action' ] );
     24                add_action( 'admin_menu', [ $this, 'register_repopackage_subpages' ] );
     25                add_action( 'add_meta_boxes', [ $this, 'suspensions_list_meta_box' ] );
     26        }
     27
     28        /**
     29         * Enqueue additional JS and CSS on the certain admin pages
     30         *
     31         * @param string $hook Page hook.
     32         */
     33        public function add_suspension_scripts( $hook ) {
     34                if ( $hook === 'repopackage_page_suspended-packages-bulk-message-page' ) {
     35                        wp_register_style( 'suspend-form', plugins_url( 'theme-directory/assets/suspend-form.css' ) );
     36                        wp_enqueue_style('suspend-form');
     37                }
     38        }
     39
     40        /**
     41         * Add additional post columns to the themes list screen
     42         *
     43         * @param array $columns Array of repo package post columns.
     44         *
     45         * @return array Updated list of post columns.
     46         */
     47        public function add_new_post_columns( array $columns ) : array {
     48                if ( ! isset( $_GET['post_status'] ) || $_GET['post_status'] !== 'suspend' ) {
     49                        return $columns;
     50                }
     51
     52                unset( $columns['tags'], $columns['theme-url'], $columns['author-url'], $columns['date'] );
     53
     54                $columns['suspended-by']           = __( 'Suspended by', 'wporg-theme' );
     55                $columns['suspension-reason']      = __( 'Reason', 'wporg-theme' );
     56                $columns['date-of-suspension']     = __( 'Date', 'wporg-theme' );
     57                $columns['suspension-expiry-date'] = __( 'Expiry', 'wporg-theme' );
     58                $columns['suspension-type']        = __( 'Suspension type', 'wporg-theme' );
     59
     60                return $columns;
     61        }
     62
     63        /**
     64         * Add content to the custom columns
     65         *
     66         * @param string $column Column name.
     67         * @param int $post_id   Current post id where this data is pulled from.
     68         *
     69         * @return void
     70         */
     71        public function add_column_content( string $column, int $post_id ) : void {
     72                if ( ! isset( $_GET['post_status'] ) || $_GET['post_status'] !== 'suspend' ) {
     73                        return;
     74                }
     75
     76                $suspension_data = get_post_meta( $post_id, 'suspension_details', true );
     77
     78                $suspended_by           = '';
     79                $suspension_reason      = '';
     80                $date_of_suspension     = '';
     81                $date_of_suspension_end = '';
     82                $suspension_type        = '';
     83
     84                if ( ! empty( $suspension_data ) ) {
     85                        $suspension_details = json_decode( $suspension_data, true );
     86
     87                        $last_suspension = end( $suspension_details );
     88
     89                        $suspended_by           = $last_suspension['suspended_by'];
     90                        $suspension_reason      = $last_suspension['suspension_description'];
     91                        $date_of_suspension     = strtotime( $last_suspension['suspended_on'] );
     92                        $date_of_suspension_end = strtotime( $last_suspension['suspension_expiration_date'] );
     93                        $suspension_type        = ucfirst( $last_suspension['suspension_type'] );
     94                }
     95
     96                switch ( $column ) {
     97                        case 'suspended-by':
     98                                echo esc_html( $suspended_by );
     99                                        break;
     100                        case 'suspension-reason':
     101                                echo wp_kses_post( $suspension_reason );
     102                                        break;
     103                        case 'date-of-suspension':
     104                                echo $date_of_suspension !== '' ? date( 'Y-m-d', $date_of_suspension ) : '';
     105                                        break;
     106                        case 'suspension-expiry-date':
     107                                echo $date_of_suspension_end !== '' ? date( 'Y-m-d', $date_of_suspension_end ) : '';
     108                                        break;
     109                        case 'suspension-type':
     110                                echo $suspension_type;
     111                                        break;
     112                        default:
     113                                echo '';
     114                                        break;
     115                }
     116        }
     117
     118        /**
     119         * List of columns that should be sortable
     120         *
     121         * @param array $columns Columns to sort.
     122         * @return array
     123         */
     124        public function make_columns_sortable( array $columns ) : array {
     125                $columns['date-of-suspension']     = 'date';
     126                $columns['suspension-expiry-date'] = 'date';
     127
     128                return $columns;
     129        }
     130
     131        /**
     132         * Add bulk suspend themes and reinstate themes options
     133         *
     134         * @param array $bulk_actions Array of default bulk options
     135         *
     136         * @return array Array of updated bulk actions
     137         */
     138        public function add_bulk_suspend_option( array $bulk_actions ) : array {
     139                $bulk_actions['suspend_themes']   = __( 'Suspend themes', 'wporg-themes' );
     140                $bulk_actions['reinstate_themes'] = __( 'Reinstate themes', 'wporg-themes' );
     141
     142                return $bulk_actions;
     143        }
     144
     145        /**
     146         * Fires when a bulk action should be handled.
     147         *
     148         * @param string $redirect_url The redirect URL.
     149         * @param string $doaction     The action being taken.
     150         * @param array  $post_ids     The items to take the action on.
     151         *
     152         * @return string
     153         */
     154        public function suspend_bulk_action_handler( string $redirect_url, string $doaction, array $post_ids ) : string {
     155                switch ( $doaction ) {
     156                        case 'suspend_themes':
     157                                return $this->suspend_themes_redirect( $post_ids );
     158                                        break;
     159                        case 'reinstate_themes':
     160                                return $this->reinstate_themes_redirect( $post_ids );
     161                                        break;
     162                        default:
     163                                return $redirect_url;
     164                                        break;
     165                }
     166        }
     167
     168        /**
     169         * Action ran on theme suspension
     170         *
     171         * This will set theme status to suspend, remove the theme from preview
     172         * and set the trac ticket to suspended status.
     173         */
     174        public function suspend_themes_action() {
     175                // Safety checks!
     176                $post_ids = ! empty( $_POST['post_ids'] ) ? explode( ',', $_POST['post_ids'] ) : [];
     177
     178                if ( empty( $post_ids )  ) {
     179                        wp_safe_redirect( admin_url( 'edit.php?post_type=repopackage&page=suspended-packages-bulk-message-page' ) );
     180                        exit;
     181                }
     182
     183                if ( ! wp_verify_nonce( $_POST['bulk_suspend_nonce'], 'bulk_suspend_action' ) ) {
     184                        wp_safe_redirect( admin_url( 'edit.php?post_type=repopackage&page=suspended-packages-bulk-message-page' ) );
     185                        exit;
     186                }
     187
     188                if ( ! isset( $_POST['bulk_suspend_nonce'] ) && $_POST['bulk_suspend_nonce'] !== 'suspend_themes' ) {
     189                        wp_safe_redirect( admin_url( 'edit.php?post_type=repopackage&page=suspended-packages-bulk-message-page' ) );
     190                        exit;
     191                }
     192
     193                $suspension_description = $_POST['suspension-description'] ?? '';
     194
     195                if ( empty( $suspension_description ) ) {
     196                        $redirect_url = admin_url('edit.php?post_type=repopackage&page=suspended-packages-bulk-message-page');
     197                        $page_url     = add_query_arg( [
     198                                'error' => __( 'Suspension description cannot be empty.', 'wporg-themes' ),
     199                                'post_ids' => $_POST['post_ids']
     200                        ], $redirect_url );
     201
     202                        wp_safe_redirect( $page_url );
     203                        exit;
     204                }
     205
     206                $suspension_expiration_date = $_POST['suspension-date-expiration'] ?? '';
     207
     208                if ( time() > strtotime( $suspension_expiration_date ) ) {
     209                        $redirect_url = admin_url('edit.php?post_type=repopackage&page=suspended-packages-bulk-message-page');
     210                        $page_url     = add_query_arg( [
     211                                'error' => __( 'Suspension expiration date cannot be in the past.', 'wporg-themes' ),
     212                                'post_ids' => $_POST['post_ids']
     213                        ], $redirect_url );
     214
     215                        wp_safe_redirect( $page_url );
     216                        exit;
     217                }
     218
     219                $suspension_type = $_POST['suspension-type'] ?? 'Temporary'; // Fall back to temporary, even though this will always be set.
     220
     221                $current_user = wp_get_current_user()->display_name;
     222                $current_time = date( 'Y-m-d' );
     223
     224                foreach ( $post_ids as $post_id ) {
     225                        wp_update_post( array(
     226                                'ID'          => $post_id,
     227                                'post_status' => 'suspend',
     228                        ) );
     229
     230                        $theme = new WPORG_Themes_Repo_Package( $post_id );
     231
     232                        // Remove from previewer.
     233                        wporg_themes_remove_wpthemescom( $theme->post_name );
     234
     235                        // Mark a theme as inactive in GlotPress.
     236                        wporg_themes_glotpress_import( $theme, 'inactive' );
     237
     238                        $suspension_data = get_post_meta( $post_id, 'suspension_details', true );
     239
     240                        $suspension_details = [];
     241
     242                        if ( ! empty( $suspension_data ) ) {
     243                                $suspension_details = json_decode( $suspension_data, true );
     244                        }
     245
     246                        $data = [
     247                                'suspended_by'               => $current_user,
     248                                'suspended_on'               => $current_time,
     249                                'suspension_description'     => $suspension_description,
     250                                'suspension_expiration_date' => $suspension_expiration_date,
     251                                'suspension_type'            => ucfirst( $suspension_type ),
     252                        ];
     253
     254                        $suspension_details[] = $data;
     255
     256                        update_post_meta( $post_id, 'suspension_details', wp_json_encode( $suspension_details ) );
     257
     258                        // Suspend on trac.
     259                        $this->suspend_theme_on_trac( $theme, $suspension_description );
     260                }
     261
     262                wp_safe_redirect( esc_url( admin_url( 'edit.php?post_type=repopackage&page=suspended-packages-page&noheader=true' ) ) );
     263                exit;
     264        }
     265
     266        /**
     267         * Register admin subpage
     268         *
     269         * Used to create bulk suspension page.
     270         */
     271        public function register_repopackage_subpages() : void {
     272                add_submenu_page(
     273                        'edit.php?post_type=repopackage',
     274                        __( 'Suspension message', 'wporg-themes' ),
     275                        __( 'Suspension message', 'wporg-themes' ),
     276                        'manage_options',
     277                        'suspended-packages-bulk-message-page',
     278                        [ $this, 'suspended_packages_bulk_message_page_callback' ]
     279                );
     280        }
     281
     282        /**
     283         * Callback for bulk message page
     284         */
     285        public function suspended_packages_bulk_message_page_callback() {
     286                ?>
     287                <div class="wrap">
     288                        <h2><?php echo get_admin_page_title(); ?></h2>
     289                        <?php
     290                                $theme_ids = $_GET['post_ids'] ?? '';
     291
     292                                $this->generate_bulk_suspension_form( esc_html( $theme_ids ) );
     293                        ?>
     294                </div>
     295                <?php
     296        }
     297
     298        /**
     299         * Meta box that will show suspensions in a theme
     300         */
     301        public function suspensions_list_meta_box() {
     302                add_meta_box(
     303                        'wporg_themes_past_suspensions',
     304                        __( 'Past suspensions', 'wporg-themes' ),
     305                        [ $this, 'suspensions_meta_box_callback' ],
     306                        'repopackage',
     307                        'normal',
     308                        'high'
     309                );
     310        }
     311        /**
     312         * Displays the content of the `_status` meta box.
     313         *
     314         * @param \WP_Post $post The current post.
     315         */
     316        public function suspensions_meta_box_callback( \WP_Post $post ) {
     317                $suspensions = get_post_meta( $post->ID, 'suspension_details', true );
     318
     319                if ( empty( $suspensions ) ) {
     320                        return;
     321                }
     322
     323                $suspension_details = json_decode( $suspensions, true );
     324
     325                foreach ( $suspension_details as $past_suspension ) {
     326                        $suspended_by               = $past_suspension['suspended_by'] ?? '';
     327                        $suspended_on               = $past_suspension['suspended_on'] ?? '';
     328                        $suspension_description     = $past_suspension['suspension_description'] ?? '';
     329                        $suspension_expiration_date = $past_suspension['suspension_expiration_date'] ?? '';
     330                        $suspension_type            = $past_suspension['suspension_type'] ?? '';
     331                        ?>
     332                        <div>
     333                                <p><?php echo '<strong>' , __( 'Suspended by: ', 'wporg-themes' ), '</strong>' , esc_html( $suspended_by ); ?></p>
     334                                <p><?php echo '<strong>' , __( 'Suspended on: ', 'wporg-themes' ), '</strong>' , esc_html( $suspended_on ); ?></p>
     335                                <p><?php echo '<strong>' , __( 'Reason for suspension: ', 'wporg-themes' ), '</strong>' , esc_html( $suspension_description ); ?></p>
     336                                <p><?php echo '<strong>' , __( 'Suspension expired: ', 'wporg-themes' ), '</strong>' , esc_html( $suspension_expiration_date ); ?></p>
     337                                <p><?php echo '<strong>' , __( 'Suspension type: ', 'wporg-themes' ), '</strong>' , esc_html( $suspension_type ); ?></p>
     338                                <hr/>
     339                        </div>
     340                        <?php
     341                }
     342        }
     343
     344        /**
     345         * Generate form that is used for theme suspension
     346         *
     347         * @param string $theme_ids Comma separated list of theme ids to suspend.
     348         */
     349        private function generate_bulk_suspension_form( $theme_ids ) {
     350
     351                $error = $_REQUEST['error'] ?? '';
     352
     353                if ( ! empty( $error ) ) {
     354                        ?>
     355                        <div class="notice error">
     356                                <?php echo '<p>' , esc_html( $error ) , '</p>' ?>
     357                        </div>
     358                        <?php
     359                }
     360
     361                if ( ! empty( $theme_ids ) ) {
     362                        $notice_text = '';
     363
     364                        foreach ( explode( ',', $theme_ids ) as $theme_id ) {
     365                                $theme = new \WPORG_Themes_Repo_Package( $theme_id );
     366
     367                                $version = $theme->version;
     368                                $ticket  = $theme->ticket;
     369
     370                                if ( ! empty( $version ) && ! empty( $ticket ) ) {
     371                                        $notice_text .= '<p><strong>' . __( 'Theme: ', 'wporg-themes' ) . '</strong>' . esc_html( $theme->post_title ) . ', v' . esc_html( $version ) .', <a href="' . esc_url( 'https://themes.trac.wordpress.org/ticket/' . $ticket ) . '" target="_blank" rel="noreferrer nofollow">#' . esc_html( $ticket ) . '</a></p>';
     372                                } else {
     373                                        $notice_text .= '<p><strong>' . __( 'Theme: ', 'wporg-themes' ) . '</strong>' . esc_html( $theme->post_title ) . '</p>';
     374                                }
     375                        }
     376
     377                        if ( ! empty( $notice_text ) ) {
     378                        ?>
     379                        <div class="notice">
     380                                <p><?php _e( 'Themes to be suspended:', 'wporg-themes' ); ?></p>
     381                                <?php echo wp_kses_post( $notice_text ); ?>
     382                        </div>
     383                        <?php
     384                        }
     385                }
     386                ?>
     387                <form method="post" class="bulk-suspension-form" action="<?php echo esc_attr( admin_url('admin-post.php') ); ?>">
     388                        <input type="hidden" name="action" value="suspend_themes">
     389                        <input type="hidden" name="post_ids" value="<?php echo esc_attr( $theme_ids ); ?>">
     390                        <?php
     391                        wp_nonce_field( 'bulk_suspend_action', 'bulk_suspend_nonce' );
     392                         ?>
     393                        <div class="fields-wrapper">
     394                                <div class="fields-row">
     395                                        <div class="fields-column"><strong><label for="suspension-description"><?php _e( 'Suspension reason', 'wporg-themes' ); ?></label></strong></div>
     396                                        <div class="fields-column"><strong><label for="suspension-date-expiration"><?php _e( 'Suspension expiration date', 'wporg-themes' ); ?></label></strong></div>
     397                                </div>
     398                                <div class="fields-row">
     399                                        <div class="fields-column"><textarea name="suspension-description" id="suspension-description" cols="70" rows="10"></textarea></div>
     400                                        <div class="fields-column">
     401                                                <input type="date" id="suspension-date-expiration" name="suspension-date-expiration" value="" class="suspension-date-expiration-datepicker" />
     402                                                <br />
     403                                                <strong><label for="suspension-type"><?php _e( 'Suspension type', 'wporg-themes' ); ?></label></strong>
     404                                                <br />
     405                                                <select name="suspension-type" id="suspension-type">
     406                                                        <option value="temporary"><?php _e( 'Temporary', 'wporg-themes' ); ?></option>
     407                                                        <option value="permanent"><?php _e( 'Permanent', 'wporg-themes' ); ?></option>
     408                                                </select>
     409                                        </div>
     410                                </div>
     411                                <div class="fields-row">
     412                                        <button type="submit" class="button button-primary"><?php _e( 'Submit', 'wporg-themes' ); ?></button>
     413                                </div>
     414                        </div>
     415                </form>
     416                <?php
     417        }
     418
     419        /**
     420         * Redirect for suspend themes bulk action.
     421         *
     422         * @param array $post_ids The items to take the action on.
     423         *
     424         * @return string
     425         */
     426        private function suspend_themes_redirect( array $post_ids ) : string {
     427                $themes_to_suspend = array_filter( $post_ids, static function( $post_id ) {
     428                        if ( get_post_status( $post_id ) !== 'suspend' ) {
     429                                return $post_id;
     430                        }
     431                } );
     432
     433                $number_of_themes_to_suspend = count( $themes_to_suspend );
     434
     435                $redirect_url = admin_url('edit.php?post_type=repopackage&page=suspended-packages-bulk-message-page');
     436                $page_url     = add_query_arg( [ 'post_ids' => implode( ',', $themes_to_suspend ), 'count' => $number_of_themes_to_suspend ], $redirect_url );
     437
     438                $redirect_to = add_query_arg( 'bulk_suspend_themes', $number_of_themes_to_suspend, $page_url );
     439
     440                return $redirect_to;
     441        }
     442
     443        /**
     444         * Redirect for suspend themes bulk action.
     445         *
     446         * @param array  $post_ids     The items to take the action on.
     447         *
     448         * @return string
     449         */
     450        private function reinstate_themes_redirect( array $post_ids ) : string {
     451                // Reinstate themes in bulk!
     452                // After themes are reinstated, add an admin notice.
     453                if ( empty( $post_ids ) ) {
     454                        return $redirect_url;
     455                }
     456
     457                $themes_to_reinstate = array_filter( $post_ids, static function( $post_id ) {
     458                        if ( get_post_status( $post_id ) === 'suspend' ) {
     459                                return $post_id;
     460                        }
     461                } );
     462
     463                foreach ( $themes_to_reinstate as $post_id ) {
     464                        $post = get_post( $post_id );
     465
     466                        if ( ! get_post_type_object( $post->post_type ) ) {
     467                                wp_die( __( 'Unknown post type.', 'wporg-themes' ) );
     468                        }
     469
     470                        if ( ! current_user_can( 'reinstate_theme', $post_id ) || 'repopackage' != $post->post_type ) {
     471                                wp_die( __( 'You are not allowed to reinstate this item.', 'wporg-themes' ) );
     472                        }
     473
     474                        wp_update_post( array(
     475                                'ID'          => $post_id,
     476                                'post_status' => 'draft',
     477                        ) );
     478
     479                        /*
     480                         * Mark it as reinstated, so the post date doesn't get overwritten when it's
     481                         * published again.
     482                         */
     483                        add_post_meta( $post_id, '_wporg_themes_reinstated', true );
     484                }
     485
     486                $number_of_reinstated_themes = count( $themes_to_reinstate );
     487
     488                wp_redirect( add_query_arg( 'reinstated', $number_of_reinstated_themes, remove_query_arg( array( 'trashed', 'untrashed', 'deleted', 'ids', 'suspended' ), wp_get_referer() ) ) );
     489                exit();
     490        }
     491
     492        /**
     493         * When suspend action is ran, suspend the theme on trac as well
     494         *
     495         * This will ensure that theme reps don't need to manually suspend a theme on trac.
     496         *
     497         * @param object $theme                  WPORG_Themes_Repo_Package object.
     498         * @param string $suspension_description Description of suspension to add to trac ticket.
     499         */
     500        private function suspend_theme_on_trac( $theme, string $suspension_description ) {
     501                if ( ! class_exists( 'Trac' ) ) {
     502                        require_once ABSPATH . WPINC . '/class-IXR.php';
     503                        require_once ABSPATH . WPINC . '/class-wp-http-ixr-client.php';
     504                        require_once __DIR__ . '/lib/class-trac.php';
     505                }
     506
     507                // Check for tickets that were set to live previously.
     508                $trac = new Trac( 'themetracbot', THEME_TRACBOT_PASSWORD, 'https://themes.trac.wordpress.org/login/xmlrpc' );
     509
     510                $ticket_id = $theme->ticket;
     511
     512                $trac->ticket_update(
     513                        $ticket_id,
     514                        $suspension_description,
     515                        [
     516                                'action' => 'review',
     517                                'status' => 'suspended',
     518                        ],
     519                        true
     520                );
     521        }
     522}
     523
  • wordpress.org/public_html/wp-content/plugins/theme-directory/theme-directory.php

    diff --git wordpress.org/public_html/wp-content/plugins/theme-directory/theme-directory.php wordpress.org/public_html/wp-content/plugins/theme-directory/theme-directory.php
    index e5796871c..a70ae779b 100644
    include __DIR__ . '/jobs/class-manager.php'; 
    3434include __DIR__ . '/jobs/class-trac-sync.php';
    3535new WordPressdotorg\Theme_Directory\Jobs\Manager();
    3636
     37// Load suspension additions.
     38include __DIR__ . '/class-wporg-themes-suspended-packages.php';
     39
     40(new WordPressdotorg\Theme_Directory\WPORG_Themes_Suspended_Packages())->register();
     41
    3742/**
    3843 * Things to change on activation.
    3944 */