Plugin Directory

Changeset 1839664


Ignore:
Timestamp:
03/13/2018 10:53:59 PM (8 years ago)
Author:
pressshack
Message:

Releasing 1.11.0

Location:
publishpress/trunk
Files:
151 added
7 deleted
63 edited

Legend:

Unmodified
Added
Removed
  • publishpress/trunk/common/css/pressshack-admin.css

    r1827070 r1839664  
    7979}
    8080
    81 .pressshack-admin-wrapper > header h1 {
     81.pressshack-admin-wrapper > header .pressshack-title {
    8282    margin: .67em 0 15px .15em;
    8383    font-weight: 600;
  • publishpress/trunk/common/php/class-module.php

    r1827070 r1839664  
    161161        public function get_post_types_for_module($module)
    162162        {
    163             return PublishPress\Util::get_post_types_for_module($module);
     163            return PublishPress\Legacy\Util::get_post_types_for_module($module);
    164164        }
    165165
     
    335335        public function get_current_post_type()
    336336        {
    337             return PublishPress\Util::get_current_post_type();
     337            return PublishPress\Legacy\Util::get_current_post_type();
    338338        }
    339339
     
    624624        public function users_select_form($selected = null, $args = null)
    625625        {
     626            global $publishpress;
    626627
    627628            // Set up arguments
     
    649650                $selected = array();
    650651            }
     652
     653            $roles = get_editable_roles();
    651654            ?>
    652655
    653656            <?php if (!empty($users)) : ?>
    654             <ul class="<?php echo esc_attr($list_class) ?>">
    655                 <?php foreach ($users as $user) : ?>
    656                     <?php $checked = (in_array($user->ID, $selected)) ? 'checked="checked"' : '';
    657                     ?>
    658                     <li>
    659                         <label for="<?php echo esc_attr($input_id . '-' . $user->ID) ?>">
    660                             <input type="checkbox" id="<?php echo esc_attr($input_id . '-' . $user->ID) ?>"
    661                                    name="<?php echo esc_attr($input_id) ?>[]" value="<?php echo esc_attr($user->ID);
    662                             ?>" <?php echo $checked;
    663                             ?> />
    664                             <span class="pp-user_displayname"><?php echo esc_html($user->display_name);
    665                                 ?></span>
    666                             <span class="pp-user_useremail"><?php echo esc_html($user->user_email);
    667                                 ?></span>
    668                         </label>
    669                     </li>
    670                 <?php endforeach;
    671                 ?>
    672             </ul>
    673         <?php endif;
    674             ?>
     657                <select class="chosen-select" name="to_notify[]" multiple>
     658                    <?php if (!empty($roles)) : ?>
     659                        <optgroup label="<?php echo __('Roles', 'publishpress'); ?>">
     660                            <?php foreach ($roles as $role => $data) : ?>
     661                                <?php $attrSelected = (in_array($role, $selected)) ? 'selected="selected"' : ''; ?>
     662                                <option value="<?php echo $role; ?>" <?php echo $attrSelected; ?>><?php echo __('Role', 'publishpress'); ?>: <?php echo $data['name']; ?></option>
     663                            <?php endforeach; ?>
     664                        </optgroup>
     665                    <?php endif; ?>
     666                    <optgroup label="<?php echo __('Users', 'publishpress'); ?>">
     667                        <?php foreach ($users as $user) : ?>
     668                            <?php $attrSelected = (in_array($user->ID, $selected)) ? 'selected="selected"' : ''; ?>
     669                            <option value="<?php echo $user->ID; ?>" <?php echo $attrSelected; ?>><?php echo $user->display_name; ?></option>
     670                        <?php endforeach; ?>
     671                    </optgroup>
     672                </select>
     673            <?php endif; ?>
    675674            <?php
    676 
    677675        }
    678676
     
    686684        {
    687685
    688             PublishPress\Util::add_caps_to_role($role, $caps);
     686            PublishPress\Legacy\Util::add_caps_to_role($role, $caps);
    689687        }
    690688
  • publishpress/trunk/includes.php

    r1827070 r1839664  
    2929 */
    3030
    31 use PublishPress\Auto_loader;
     31use PublishPress\Legacy\Auto_loader;
    3232
    33 if (!defined('PP_LOADED'))
    34 {
     33if (!defined('PP_LOADED')) {
    3534    $settingsPage = add_query_arg(
    3635        array(
     
    4241
    4342    // Define contants
    44     define('PUBLISHPRESS_VERSION', '1.10.0');
    45     define('PUBLISHPRESS_ROOT', dirname(__FILE__));
    46     define('PUBLISHPRESS_FILE_PATH', PUBLISHPRESS_ROOT . '/' . basename(__FILE__));
     43    define('PUBLISHPRESS_VERSION', '1.11.0');
     44    define('PUBLISHPRESS_BASE_PATH', __DIR__);
     45    define('PUBLISHPRESS_FILE_PATH', PUBLISHPRESS_BASE_PATH . '/' . basename(__FILE__));
    4746    define('PUBLISHPRESS_URL', plugins_url('/', __FILE__));
    4847    define('PUBLISHPRESS_SETTINGS_PAGE', $settingsPage);
    49     define('PUBLISHPRESS_LIBRARIES_PATH', PUBLISHPRESS_ROOT . '/libraries');
     48    define('PUBLISHPRESS_LIBRARIES_PATH', PUBLISHPRESS_BASE_PATH . '/libraries');
     49
     50    /**
     51     * Use PUBLISHPRESS_BASE_PATH instead.
     52     *
     53     * @deprecated
     54     */
     55    define('PUBLISHPRESS_ROOT', PUBLISHPRESS_BASE_PATH);
    5056
    5157    // Define the Priority for the notification/notification_status_change method
    5258    // Added to allow users select a custom priority
    53     if (!defined('PP_NOTIFICATION_PRIORITY_STATUS_CHANGE'))
    54     {
     59    if (!defined('PP_NOTIFICATION_PRIORITY_STATUS_CHANGE')) {
    5560        define('PP_NOTIFICATION_PRIORITY_STATUS_CHANGE', 10);
    5661    }
    5762
    58     require_once PUBLISHPRESS_ROOT . '/vendor/autoload.php';
     63    if (file_exists(PUBLISHPRESS_BASE_PATH . '/vendor/autoload.php')) {
     64        require_once PUBLISHPRESS_BASE_PATH . '/vendor/autoload.php';
     65    }
    5966
    6067    // Register the autoloader
    61     if (!class_exists('\\PublishPress\\Auto_loader'))
    62     {
    63         require_once PUBLISHPRESS_LIBRARIES_PATH . '/Auto_loader.php';
     68    if (!class_exists('\\PublishPress\\Legacy\\Auto_loader')) {
     69        require_once PUBLISHPRESS_LIBRARIES_PATH . '/Legacy/Auto_loader.php';
    6470    }
    6571
    6672    // Register the library
    67     Auto_loader::register('\\PublishPress\\', PUBLISHPRESS_LIBRARIES_PATH);
     73    Auto_loader::register('\\PublishPress\\Legacy\\', PUBLISHPRESS_LIBRARIES_PATH . '/Legacy');
     74    Auto_loader::register('\\PublishPress\\Notifications\\', PUBLISHPRESS_LIBRARIES_PATH . '/Notifications');
     75
     76    require_once PUBLISHPRESS_BASE_PATH . '/deprecated.php';
    6877
    6978    define('PP_LOADED', 1);
  • publishpress/trunk/includes_notifications.php

    r1827070 r1839664  
    1010 */
    1111
    12 use PublishPress\Notifications\Auto_loader;
    13 
    1412defined('ABSPATH') or die('No direct script access allowed.');
    15 
    16 require_once 'vendor/autoload.php';
    1713
    1814if (!defined('PUBLISHPRESS_NOTIF_LOADED'))
    1915{
    2016    define('PUBLISHPRESS_NOTIF_MODULE_PATH', __DIR__ . '/modules/improved-notifications');
    21     define('PUBLISHPRESS_NOTIF_TWIG_PATH', PUBLISHPRESS_ROOT . '/twig');
     17    define('PUBLISHPRESS_NOTIF_TWIG_PATH', PUBLISHPRESS_BASE_PATH . '/twig');
    2218    define('PUBLISHPRESS_NOTIF_LOADED', 1);
    2319
  • publishpress/trunk/libraries/Notifications/Workflow/Controller.php

    r1827070 r1839664  
    139139            '\\PublishPress\\Notifications\\Workflow\\Step\\Receiver\\Author',
    140140            '\\PublishPress\\Notifications\\Workflow\\Step\\Receiver\\User',
    141             '\\PublishPress\\Notifications\\Workflow\\Step\\Receiver\\User_Group',
     141            '\\PublishPress\\Notifications\\Workflow\\Step\\Receiver\\Role',
    142142            '\\PublishPress\\Notifications\\Workflow\\Step\\Receiver\\Follower',
    143143        ];
  • publishpress/trunk/libraries/Notifications/Workflow/Step/Channel/Email.php

    r1827070 r1839664  
    4646        if (empty($receivers)) {
    4747            return;
     48        }
     49
     50        // Make sure we unserialize the content when it comes from async notifications.
     51        if (is_string($content)) {
     52            $content = maybe_unserialize($content);
    4853        }
    4954
  • publishpress/trunk/libraries/Notifications/Workflow/Step/Event/Filter/Base.php

    r1827070 r1839664  
    4141     *
    4242     * @return string
     43     *
     44     * @throws \Exception
    4345     */
    4446    public function render()
  • publishpress/trunk/libraries/Notifications/Workflow/Step/Event/Filter/Post_Status.php

    r1827070 r1839664  
    5050    {
    5151        $statuses = $this->get_post_statuses();
     52        $metadata = (array)$this->get_metadata('');
    5253        $options  = [];
    53         $metadata = (array)$this->get_metadata('');
     54
     55        if ('from' === $group) {
     56            // Add an status to represent new posts
     57            $options = [
     58                [
     59                    'value'    => 'auto-draft',
     60                    'label'    => __('"New"', 'publishpress'),
     61                    'selected' => in_array('auto-draft', $metadata[$group]),
     62                ],
     63            ];
     64        }
    5465
    5566        foreach ($statuses as $status)
  • publishpress/trunk/libraries/Notifications/Workflow/Step/Receiver/Follower.php

    r1827070 r1839664  
    4646        if ($this->is_selected($workflow->ID))
    4747        {
    48 
    4948            $post_id = $args['post']->ID;
    5049
     
    5655            $followers = array();
    5756
    58             if ($publishpress->improved_notifications->module_enabled('user_groups'))
    59             {
    60                 // Get following users and usergroups
    61                 $usergroups = $publishpress->notifications->get_following_usergroups($post_id, 'ids');
    6257
    63                 foreach ((array)$usergroups as $usergroup_id)
     58            // Check if we just created the post and the metadata is not saved yet.
     59            if ('POST' === $_SERVER['REQUEST_METHOD']
     60                && (isset($_POST['action']) && 'editpost' === $_POST['action'])
     61                && (isset($_POST['original_post_status']) && 'auto-draft' === $_POST['original_post_status'])
     62            ) {
     63                $toNotify = $_POST['to_notify'];
     64
     65                $roles = array();
     66                $users = array();
     67
     68                foreach ($toNotify as $item) {
     69                    if (is_numeric($item)) {
     70                        $users[] = $item;
     71                    } else {
     72                        $roles[] = $item;
     73                    }
     74                }
     75            } else {
     76                // Get following users and roles
     77                $roles = $publishpress->notifications->get_roles_to_notify($post_id, 'slugs');
     78                $users = $publishpress->notifications->get_users_to_notify($post_id, 'id');
     79            }
     80
     81            // Extract users from roles
     82            if (!empty($roles)) {
     83                foreach ($roles as $role)
    6484                {
    65                     $usergroup = $publishpress->user_groups->get_usergroup_by('id', $usergroup_id);
     85                    $roleUsers = get_users(
     86                        [
     87                            'role' => $role,
     88                        ]
     89                    );
    6690
    67                     foreach ((array)$usergroup->user_ids as $user_id)
    68                     {
    69                         $usergroup_user = get_user_by('id', $user_id);
    70 
    71                         if ($usergroup_user && is_user_member_of_blog($user_id))
     91                    if (!empty($roleUsers)) {
     92                        foreach ($roleUsers as $user)
    7293                        {
    73                             $followers[] = $usergroup_user;
     94                            if (is_user_member_of_blog($user->ID))
     95                            {
     96                                $followers[] = $user->ID;
     97                            }
    7498                        }
    7599                    }
     
    77101            }
    78102
    79             $users = $publishpress->notifications->get_following_users($post_id, 'object');
    80 
    81             // Merge usergroup users and users
     103            // Merge roles' users and users
    82104            $followers = array_merge($followers, $users);
    83105
    84106            // Process the recipients for this email to be sent
    85             foreach ($followers as $key => $user)
    86             {
     107            if (!empty($followers)) {
     108                foreach ($followers as $key => $user)
     109                {
     110                    // Make sure we have only user objects in the list
     111                    if (is_numeric($user)) {
     112                        $user = get_user_by('ID', $user);
     113                    }
    87114
    88                 // Don't send the email to the current user unless we've explicitly indicated they should receive it
    89                 if (false === apply_filters('pp_notification_email_current_user', false) && wp_get_current_user()->user_email == $user->user_email)
    90                 {
    91                     unset($followers[$key]);
     115                    // Don't send the email to the current user unless we've explicitly indicated they should receive it
     116                    if (false === apply_filters('publishpress_notify_current_user', false) && wp_get_current_user()->user_email == $user->user_email)
     117                    {
     118                        unset($followers[$key]);
     119                    }
    92120                }
    93121            }
     
    107135                foreach ($followers as $user)
    108136                {
    109                     $receivers[] = $user->ID;
     137                    if (is_object($user)) {
     138                        $receivers[] = $user->ID;
     139                    } else {
     140                        $receivers[] = $user;
     141                    }
    110142                }
    111143            }
  • publishpress/trunk/libraries/Notifications/Workflow/Step/Receiver/User.php

    r1827070 r1839664  
    112112        $template_context['list_class'] = 'publishpress_notif_user_list';
    113113        $template_context['input_name'] = 'publishpress_notif[receiver_user][]';
    114         $template_context['input_id']   = 'publishpress_notif_user_';
     114        $template_context['input_id']   = 'publishpress_notif_user_list';
    115115
    116116        $template_context = parent::filter_workflow_metabox_context($template_context);
     
    137137
    138138            // Get the users following the post
    139             $users     = $this->get_service('publishpress')->notifications->get_following_users($args['post']->ID, 'id');
     139            $users     = $this->get_service('publishpress')->notifications->get_users_to_notify($args['post']->ID, 'id');
    140140            $receivers = array_merge($receivers, $users);
    141141
  • publishpress/trunk/modules/addons/addons.php

    r1827070 r1839664  
    136136        protected function is_plugin_installed($plugin)
    137137        {
    138             return file_exists(plugin_dir_path(PUBLISHPRESS_ROOT) . "{$plugin}/{$plugin}.php");
     138            return file_exists(plugin_dir_path(PUBLISHPRESS_BASE_PATH) . "{$plugin}/{$plugin}.php");
    139139        }
    140140
  • publishpress/trunk/modules/async-notifications/async-notifications.php

    r1827070 r1839664  
    2929 */
    3030
    31 use PublishPress\Auto_loader;
     31use PublishPress\Legacy\Auto_loader;
    3232use PublishPress\Notifications\Traits\Dependency_Injector;
    3333use PublishPress\Notifications\Traits\PublishPress_Module;
     
    8989            $args['default_options'] = apply_filters('publishpress_async_notif_default_options', $args['default_options']);
    9090            $this->module            = $publishpress->register_module(
    91                 PublishPress\Util::sanitize_module_name($this->module_name),
     91                PublishPress\Legacy\Util::sanitize_module_name($this->module_name),
    9292                $args
    9393            );
     
    183183            ];
    184184            $receivers    = [$receiver];
     185
     186            // Decode the content
     187            $content = base64_decode(maybe_unserialize($content));
    185188
    186189            /**
  • publishpress/trunk/modules/async-notifications/library/Queue/WPCron.php

    r1827070 r1839664  
    5555        if (!empty($receivers))
    5656        {
    57             $data = [
    58                 'workflow_post_id' => $workflowPost->ID,
    59                 'action'           => $actionArgs['action'],
    60                 'post_id'          => $actionArgs['post']->ID,
    61                 'content'          => $content,
    62                 'old_status'       => isset($actionArgs['old_status']) ? $actionArgs['old_status'] : null,
    63                 'new_status'       => isset($actionArgs['new_status']) ? $actionArgs['new_status'] : null,
    64                 'channel'          => $channel,
     57            $baseData = [
     58                // workflow_post_id
     59                $workflowPost->ID,
     60                // action
     61                $actionArgs['action'],
     62                // post_id
     63                $actionArgs['post']->ID,
     64                // content
     65                base64_encode(maybe_serialize($content)),
     66                // old_status
     67                isset($actionArgs['old_status']) ? $actionArgs['old_status'] : null,
     68                // new_status
     69                isset($actionArgs['new_status']) ? $actionArgs['new_status'] : null,
     70                // channel
     71                $channel,
    6572            ];
    6673
     
    6875            foreach ($receivers as $receiver)
    6976            {
    70                 $data['receiver'] = $receiver;
     77                // Base data
     78                $data = $baseData;
     79
     80                // Receiver
     81                $data[] = $receiver;
    7182
    7283                $this->scheduleEvent($data);
  • publishpress/trunk/modules/calendar/calendar.php

    r1827070 r1839664  
    184184            $this->create_post_cap = apply_filters('pp_calendar_create_post_cap', 'edit_posts');
    185185
    186             require_once(PUBLISHPRESS_ROOT . '/common/php/' . 'screen-options.php');
     186            require_once(PUBLISHPRESS_BASE_PATH . '/common/php/' . 'screen-options.php');
    187187
    188188            add_action('admin_init', array($this, 'register_settings'));
  • publishpress/trunk/modules/calendar/lib/calendar.css

    r1827070 r1839664  
    614614    }
    615615}
     616
     617#publishpress-ics-copy .dashicons,
     618#publishpress-ics-download .dashicons {
     619    margin-top: 4px;
     620    margin-right: 2px;
     621}
     622
  • publishpress/trunk/modules/content-overview/content-overview.php

    r1827070 r1839664  
    147147        add_action('admin_init', array($this, 'handle_form_date_range_change'));
    148148
    149         include_once PUBLISHPRESS_ROOT . '/common/php/' . 'screen-options.php';
     149        include_once PUBLISHPRESS_BASE_PATH . '/common/php/' . 'screen-options.php';
    150150
    151151        if (function_exists('add_screen_options_panel'))
  • publishpress/trunk/modules/custom-status/custom-status.php

    r1827070 r1839664  
    216216        {
    217217            $default_terms = $this->get_default_terms();
     218            $roles         = ['administrator', 'author', 'editor', 'contributor'];
    218219
    219220            // Okay, now add the default statuses to the db if they don't already exist
     
    223224                {
    224225                    $this->add_custom_status($term['term'], $term['args']);
     226                }
     227            }
     228
     229            // Add basic capabilities for each post status
     230            $default_terms['publish'] = array();
     231            foreach ($default_terms as $termSlug => $data)
     232            {
     233                foreach ($roles as $roleName) {
     234                    $role = get_role($roleName);
     235                    $role->add_cap('status_change_' . str_replace('-', '_', $termSlug));
     236
     237                    if ('publish' === $termSlug) {
     238                        $role->add_cap('status_change_private');
     239                        $role->add_cap('status_change_future');
     240                    }
    225241                }
    226242            }
     
    927943            $this->custom_statuses_cache = array();
    928944
     945            // Set permissions for the base roles
     946            $roles = ['administrator', 'editor', 'author', 'contributor'];
     947            foreach ($roles as $roleSlug) {
     948                $role = get_role($roleSlug);
     949                if (!empty($role)) {
     950                    $role->add_cap('status_change_' . str_replace('-', '_', $slug));
     951                }
     952            }
     953
    929954            return $response;
    930955        }
  • publishpress/trunk/modules/dashboard/dashboard.php

    r1827070 r1839664  
    247247            global $publishpress;
    248248
    249             $myposts = $publishpress->notifications->get_user_following_posts();
     249            $myposts = $publishpress->notifications->get_user_to_notify_posts();
    250250
    251251            ?>
  • publishpress/trunk/modules/improved-notifications/assets/css/admin.css

    r1827070 r1839664  
    9393}
    9494
    95 #psppno-workflow-metabox-section-receiver #pp-post_following_users_box {
     95#psppno-workflow-metabox-section-receiver #pp_post_notify_users_box {
    9696    float: none;
    9797    margin-right: 0;
    9898}
    9999
    100 #psppno-workflow-metabox-section-receiver #pp-post_following_users_box,
     100#psppno-workflow-metabox-section-receiver #pp_post_notify_users_box,
    101101#psppno-workflow-metabox-section-receiver #pp-post_following_usergroups_box {
    102102    width: 100%;
     
    112112
    113113#psppno-workflow-metabox-section-receiver .publishpress_notif_user_list,
    114 #psppno-workflow-metabox-section-receiver .publishpress_notif_user_group_list {
     114#psppno-workflow-metabox-section-receiver .publishpress_notif_role_list {
    115115    margin-bottom: 9px;
    116116}
     
    168168}
    169169
    170 /* Branding for pages */
    171 body.post-type-psppnotif_workflow h1.wp-heading-inline:before {
    172     display: block;
    173     padding: 10px 0 10px 55px;
    174     background-image: url(../../../settings/lib/icon-128x128.png);
    175     background-size: 45px auto;
    176     background-position: left center;
    177     background-repeat: no-repeat;
    178     background-color: transparent;
    179     content: 'PublishPress';
    180     font-weight: bold;
    181     font-size: 26px;
    182     margin-bottom: 15px;
    183     margin-top: 8px;
    184     margin-left: 4px;
    185     margin-right: 0;
    186     padding-bottom: 10px;
    187     padding-left: 55px;
    188     padding-right: 0px;
    189     padding-top: 10px;
    190 }
    191 
    192170body.post-type-psppnotif_workflow #wpbody-content {
    193171    margin-bottom: 100px;
     
    211189    border-left: 8px solid #f3f3f3;
    212190}
     191
     192
     193.psppno_workflow_metabox_section_header.invalid {
     194    background-color: #ff8585 !important;
     195}
  • publishpress/trunk/modules/improved-notifications/assets/js/workflow_form.js

    r1827070 r1839664  
    4444        setupFieldFilters('event_content_category');
    4545        setupFieldFilters('user');
    46         setupFieldFilters('user_group');
     46        setupFieldFilters('role');
    4747
    4848        // List search
    49         // $('.publishpress-filter-checkbox-list ul').listFilterizer();
    5049        $('.publishpress-filter-checkbox-list select').multipleSelect({
    5150            filter: true
     
    5352
    5453        // Form validation
    55 
     54        $('form#post').on('submit', function (event) {
     55            var selected,
     56                sections = ['event', 'event_content'],
     57                messages = [];
     58
     59            /**
     60             * Set the validation status to the given section.
     61             *
     62             * @param section
     63             * @param status
     64             */
     65            function set_validation_status(section, status) {
     66                var selector = '#psppno-workflow-metabox-section-' + section + ' .psppno_workflow_metabox_section_header';
     67
     68                if (status) {
     69                    $(selector).removeClass('invalid');
     70                } else {
     71                    $(selector).addClass('invalid');
     72                }
     73            }
     74
     75            function set_tooltip(section) {
     76                var selector = '#psppno-workflow-metabox-section-' + section + ' .psppno_workflow_metabox_section_header';
     77
     78                $(selector).tooltip();
     79            }
     80
     81            // Check the Event and Event Content sections
     82            $.each(sections, function (index, section) {
     83                // Check if the "When" and "Which content" filter has at least one selected option.
     84                selected = $('[name="publishpress_notif[' + section + '][]"]:checked').length;
     85
     86                if (selected === 0) {
     87                    set_validation_status(section, false);
     88
     89                        messages.push(workflowFormData.messages['selectAllIn_' + section]);
     90                } else {
     91                    set_validation_status(section, true);
     92                }
     93            });
     94
     95            // Check if any status was selected for "moving to new status"
     96            if ($('#publishpress_notif_event_post_save:checked').length > 0) {
     97                if ($('#publishpress_notif_event_post_save_filters_post_status_from').val() == null
     98                    || $('#publishpress_notif_event_post_save_filters_post_status_to').val() == null) {
     99
     100                    set_validation_status('event', false);
     101
     102                    if ($('#publishpress_notif_event_post_save_filters_post_status_from').val() == null) {
     103                        messages.push(workflowFormData.messages['selectAPreviousStatus']);
     104                    }
     105
     106                    if ($('#publishpress_notif_event_post_save_filters_post_status_to').val() == null) {
     107                        messages.push(workflowFormData.messages['selectANewStatus']);
     108                    }
     109                } else {
     110                    set_validation_status('event', true);
     111                }
     112            }
     113
     114            // Check if any post type was selected (if checked)
     115            if ($('#publishpress_notif_event_content_post_type:checked').length > 0) {
     116                if ($('#publishpress_notif_event_content_post_type_filters_post_type').val() == null) {
     117                    set_validation_status('event_content', false);
     118
     119                    messages.push(workflowFormData.messages['selectPostType']);
     120                } else {
     121                    set_validation_status('event_content', true);
     122                }
     123            }
     124
     125            // Check if any category was selected (if checked)
     126            if ($('#publishpress_notif_event_content_category:checked').length > 0) {
     127                if ($('#publishpress_notif_event_content_category_filters_category').val() == null) {
     128                    set_validation_status('event_content', false);
     129
     130                    messages.push(workflowFormData.messages['selectCategory']);
     131                } else {
     132                    set_validation_status('event_content', true);
     133                }
     134            }
     135
     136            // Check the Receivers section
     137            if ($('#psppno-workflow-metabox-section-receiver input[type="checkbox"][name^="publishpress_notif"]:checked').length === 0) {
     138                set_validation_status('receiver', false);
     139
     140                messages.push(workflowFormData.messages['selectAReceiver']);
     141            } else {
     142                set_validation_status('receiver', true);
     143            }
     144
     145            // Check if any user was selected (if checked)
     146            if ($('#publishpress_notif_user:checked').length > 0) {
     147                if ($('#publishpress_notif_user_list').val() == null) {
     148                    set_validation_status('receiver', false);
     149
     150                    messages.push(workflowFormData.messages['selectAUser']);
     151                } else {
     152                    set_validation_status('receiver', true);
     153                }
     154            }
     155
     156            // Check if any role was selected (if checked)
     157            if ($('#publishpress_notif_role:checked').length > 0) {
     158                if ($('#publishpress_notif_roles').val() == null) {
     159                    set_validation_status('receiver', false);
     160
     161                    messages.push(workflowFormData.messages['selectARole']);
     162                } else {
     163                    set_validation_status('receiver', true);
     164                }
     165            }
     166
     167            // Check the Content section
     168            if ($('#publishpress_notification_content_main_subject').val().trim() == ''
     169                || tinymce.activeEditor.getContent().trim() === '') {
     170                set_validation_status('content', false);
     171
     172                if ($('#publishpress_notification_content_main_subject').val().trim() == '') {
     173                    messages.push(workflowFormData.messages['setASubject']);
     174                }
     175
     176                if (tinymce.activeEditor.getContent().trim() === '') {
     177                    messages.push(workflowFormData.messages['setABody']);
     178                }
     179            } else {
     180                set_validation_status('content', true);
     181            }
     182
     183            var valid = $('form#post .invalid').length === 0;
     184
     185            if (!valid) {
     186                if (messages.length > 0) {
     187                    $('#error_messages').remove();
     188                    var $messageBox = $('<div id="error_messages" class="notice notice-error"></div>');
     189                    $('.wp-header-end').after($messageBox);
     190
     191                    for (var i = 0; i < messages.length; i++) {
     192                        $element = $('<p>');
     193                        $element.text(messages[i]);
     194                        $messageBox.append($element);
     195                    }
     196                }
     197            } else {
     198                $('#error_messages').remove();
     199            }
     200
     201            return valid;
     202        });
    56203    });
    57204})(jQuery);
  • publishpress/trunk/modules/improved-notifications/improved-notifications.php

    r1827070 r1839664  
    103103            $args['default_options'] = apply_filters('publishpress_notif_default_options', $args['default_options']);
    104104            $this->module            = $publishpress->register_module(
    105                 PublishPress\Util::sanitize_module_name($this->module_name),
     105                PublishPress\Legacy\Util::sanitize_module_name($this->module_name),
    106106                $args
    107107            );
     
    362362                }
    363363            }
    364         }
     364
     365            if (version_compare($previous_version, '1.10', '<=')) {
     366                $this->migrate_legacy_metadata_for_role();
     367            }
     368        }
     369
     370        protected function migrate_legacy_metadata_for_role()
     371        {
     372            global $wpdb;
     373
     374            $query = "UPDATE {$wpdb->prefix}postmeta SET meta_key = '_psppno_torole' WHERE meta_key = '_psppno_togroup'";
     375            $wpdb->query($query);
     376
     377            $query = "UPDATE {$wpdb->prefix}postmeta SET meta_key = '_psppno_torolelist' WHERE meta_key = '_psppno_togrouplist'";
     378            $wpdb->query($query);
     379        }
     380
    365381
    366382        /**
     
    451467            if (in_array($hook_suffix, ['post.php', 'post-new.php']))
    452468            {
    453                 wp_enqueue_script('psppno-workflow-form', plugin_dir_url(__FILE__) . 'assets/js/workflow_form.js', [], PUBLISHPRESS_VERSION);
    454                 wp_enqueue_script('psppno-multiple-select', plugin_dir_url(__FILE__) . 'assets/js/multiple-select.js', [], PUBLISHPRESS_VERSION);
     469                wp_enqueue_script('psppno-multiple-select', plugin_dir_url(__FILE__) . 'assets/js/multiple-select.js', ['jquery'], PUBLISHPRESS_VERSION);
     470                wp_enqueue_script('psppno-workflow-tooltip', plugin_dir_url(__FILE__) . 'libs/opentip/downloads/opentip-jquery.js', ['jquery'], PUBLISHPRESS_VERSION);
     471                wp_enqueue_script('psppno-workflow-form', plugin_dir_url(__FILE__) . 'assets/js/workflow_form.js', ['jquery', 'psppno-workflow-tooltip', 'psppno-multiple-select'], PUBLISHPRESS_VERSION);
     472
     473                wp_localize_script(
     474                    'psppno-workflow-form',
     475                    'workflowFormData',
     476                    [
     477                        'messages' => [
     478                            'selectAllIn_event'         => 'Select at least one event.',
     479                            'selectAllIn_event_content' => 'Select at least a filter for the content.',
     480                            'selectAPreviousStatus'     => 'Select at least one previous status.',
     481                            'selectANewStatus'          => 'Select at least one new status.',
     482                            'selectPostType'            => 'Select at least one post type.',
     483                            'selectCategory'            => 'Select at least one category.',
     484                            'selectAReceiver'           => 'Select at least one receiver.',
     485                            'selectAUser'               => 'Select at least one user.',
     486                            'selectARole'               => 'Select at least one role.',
     487                            'setASubject'               => 'Type a subject for the notification.',
     488                            'setABody'                  => 'Type a body text for the notification.',
     489                        ],
     490                    ]
     491                );
    455492            }
    456493        }
     
    526563            $context = [
    527564                'id'     => 'event_content',
    528                 'header' => __('Filter the content?', 'publishpress'),
     565                'header' => __('For which content?', 'publishpress'),
    529566                'html'   => apply_filters('publishpress_notif_render_metabox_section_event_content', ''),
    530567                'class'  => 'pure-u-1-3 pure-u-sm-1 pure-u-md-1-2 pure-u-lg-1-3',
     
    571608            $context = [
    572609                'labels' => [
     610                    'validation_help'  => __('Select at least one option for each section.', 'publishpress'),
    573611                    'pre_text'         => __('You can add dynamic information to the Subject or Body text using the following shortcodes:', 'publishpress'),
    574612                    'content'          => __('Content', 'publishpress'),
     
    597635         * @param int     $id   Unique ID for the post being saved
    598636         * @param WP_Post $post Post object
     637         *
     638         * @return int|null
    599639         */
    600640        public function save_meta_boxes($id, $post)
  • publishpress/trunk/modules/notifications/assets/notifications.css

    r1827070 r1839664  
    77}
    88
    9 .pp-post_following_list {
     9.pp_post_notify_list {
    1010}
    1111
    12 .pp-post_following_list li {
     12.pp_post_notify_list li {
    1313    padding: 10px 5px 5px 5px;
    1414    margin: 0;
     
    1616}
    1717
    18 .pp-post_following_list li:hover {
     18.pp_post_notify_list li:hover {
    1919    background: #EAF2FA;
    2020}
    2121
    22 .pp-post_following_list li input {
     22.pp_post_notify_list li input {
    2323    float: right;
    2424}
    2525
    26 .pp-post_following_list .pp-user_displayname,
    27 .pp-post_following_list .pp-usergroup_name {
     26.pp_post_notify_list .pp-user_displayname,
     27.pp_post_notify_list .pp-usergroup_name {
    2828    display: block;
    2929    font-size: 14px;
    3030}
    3131
    32 .pp-post_following_list .pp-user_useremail,
    33 .pp-post_following_list .pp-usergroup_description {
     32.pp_post_notify_list .pp-user_useremail,
     33.pp_post_notify_list .pp-usergroup_description {
    3434    display: block;
    3535    color: #ccc;
     
    3737}
    3838
    39 #pp-post_following_box {
     39#pp_post_notify_box {
    4040    margin: 10px 0;
    4141}
    4242
    43 #pp-post_following_box h4 {
     43#pp_post_notify_box h4 {
    4444    background: #F1F1F1;
    4545    font-weight: bold;
     
    5050}
    5151
    52 #pp-post_following_box .error {
     52#pp_post_notify_box .error {
    5353    color: red;
    5454}
    5555
    56 #pp-post_following_box label.pp-select_all_box {
     56#pp_post_notify_box label.pp-select_all_box {
    5757    float: right;
    5858    margin: -20px 10px;
    5959}
    6060
    61 #pp-post_following_box label.pp-select_all_box input {
     61#pp_post_notify_box label.pp-select_all_box input {
    6262    margin-bottom: 5px;
    6363}
    64 
    65 #pp-post_following_users_box,
    66 #pp-post_following_usergroups_box {
    67     width: 49%;
    68 }
    69 
    70 #pp-post_following_users_box {
    71     float: left;
    72     margin-right: 10px;
    73 }
    74 
    75 #pp-post_following_usergroups_box {
    76     float: right;
    77 }
    78 
    79 #pp-post_following_users_box .pp-post_following_list,
    80 #pp-post_following_usergroups_box .pp-post_following_list {
    81     max-height: 300px !important;
    82     overflow: auto !important;
    83 }
    84 
    85 #pp-post_following_users_box .list-filterizer-tools,
    86 #pp-post_following_usergroups_box .list-filterizer-tools {
    87     margin-top: 5px;
    88 }
    89 
    90 /** User Groups **/
    91 #profile-page #post_following_usergroups {
    92     width: 300px;
    93 }
    94 
    95 #pp-usergroup-users form.quicksearch,
    96 #pp-post_following_users_box form.quicksearch {
    97     display: none;
    98 }
    99 
    100 #pp-usergroup-users h4 {
    101     margin-top: 0;
    102 }
  • publishpress/trunk/modules/notifications/assets/notifications.js

    r1827070 r1839664  
    1 jQuery(document).ready(function ($) {
    2     $('#pp-post_following_users_box ul').listFilterizer();
    3 
    4     var params = {
    5         action: 'save_notifications',
    6         post_id: $('#post_ID').val(),
    7     };
    8 
    9     $(document).on('click', '.pp-post_following_list li input:checkbox, .pp-following_usergroups li input:checkbox', function () {
    10         var user_group_ids = [];
    11         var parent_this = $(this);
    12         params.pp_notifications_name = $(this).attr('name');
    13         params._nonce = $("#pp_notifications_nonce").val();
    14 
    15         $(this)
    16             .parent()
    17             .parent()
    18             .parent()
    19             .find('input:checked')
    20             .map(function () {
    21                 user_group_ids.push($(this).val());
    22             })
    23 
    24         params.user_group_ids = user_group_ids;
    25 
    26         $.ajax({
    27             type: 'POST',
    28             url: (ajaxurl) ? ajaxurl : wpListL10n.url,
    29             data: params,
    30             success: function (x) {
    31                 var backgroundColor = parent_this.css('background-color');
    32                 $(parent_this.parent().parent())
    33                     .animate({'backgroundColor': '#CCEEBB'}, 200)
    34                     .animate({'backgroundColor': backgroundColor}, 200);
    35             },
    36             error: function (r) {
    37                 $('#pp-post_following_users_box').prev().append(' <p class="error">There was an error. Please reload the page.</p>');
    38             }
    39         });
     1jQuery(function ($) {
     2    $(".chosen-select").chosen({
     3        'width': '95%'
    404    });
    415});
  • publishpress/trunk/modules/notifications/notifications.php

    r1827070 r1839664  
    4343    {
    4444
    45         // Taxonomy name used to store users following posts
    46         public $following_users_taxonomy = 'following_users';
    47 
    48         // Taxonomy name used to store user groups following posts
    49         public $following_usergroups_taxonomy = PP_User_Groups::taxonomy_key;
     45        // Taxonomy name used to store users which will be notified for changes in the posts.
     46        public $notify_user_taxonomy = 'pp_notify_user';
     47
     48        // Taxonomy name used to store roles which will be notified for changes in the posts.
     49        public $notify_role_taxonomy = 'pp_notify_role';
    5050
    5151        public $module;
     
    6464                'title'                 => __('Default Notifications', 'publishpress'),
    6565                'short_description'     => __('With notifications, you can keep everyone updated about what’s happening with your content.', 'publishpress'),
    66                 'extended_description'  => __('With notifications, you can keep everyone updated about what’s happening with a given content. Each status change or editorial comment sends out a message to users subscribed to a post. User groups can be used to manage who receives notifications on what.', 'publishpress'),
     66                'extended_description'  => __('With notifications, you can keep everyone updated about what’s happening with a given content. Each status change or editorial comment sends out a message to users subscribed to a post. Roles can be used to manage who receives notifications on what.', 'publishpress'),
    6767                'module_url'            => $this->module_url,
    6868                'icon_class'            => 'dashicons dashicons-email',
     
    8383                    'id'      => 'pp-notifications-overview',
    8484                    'title'   => __('Overview', 'publishpress'),
    85                     'content' => __('<p>Notifications ensure you keep up to date with progress your most important content. Users can be subscribed to notifications on a post one by one or by selecting user groups.</p><p>When enabled, notifications can be sent when a post changes status or an editorial comment is left by a writer or an editor.</p>', 'publishpress'),
     85                    'content' => __('<p>Notifications ensure you keep up to date with progress your most important content. Users can be subscribed to notifications on a post one by one or by selecting roles.</p><p>When enabled, notifications can be sent when a post changes status or an editorial comment is left by a writer or an editor.</p>', 'publishpress'),
    8686                ),
    8787                'settings_help_sidebar' => __('<p><strong>For more information:</strong></p><p><a href="https://publishpress.com/features/notifications/">Notifications Documentation</a></p><p><a href="https://github.com/ostraining/PublishPress">PublishPress on Github</a></p>', 'publishpress'),
     
    107107
    108108            // Saving post actions
    109             // self::save_post_subscriptions() is hooked into transition_post_status so we can ensure usergroup data
     109            // self::save_post_subscriptions() is hooked into transition_post_status so we can ensure role data
    110110            // is properly saved before sending notifs
    111             add_action('transition_post_status', array($this, 'save_post_subscriptions'), 0, 3);
    112111            add_action('transition_post_status', array($this, 'notification_status_change'), PP_NOTIFICATION_PRIORITY_STATUS_CHANGE, 3);
    113112            add_action('pp_post_insert_editorial_comment', array($this, 'notification_comment'));
     
    121120            add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_styles'));
    122121
    123             // Add a "Follow" link to posts
    124             if (apply_filters('pp_notifications_show_follow_link', true))
    125             {
    126                 // A little extra JS for the follow button
    127                 add_action('admin_head', array($this, 'action_admin_head_follow_js'));
     122            // Add a "Notify" link to posts
     123            if (apply_filters('pp_notifications_show_notify_link', true))
     124            {
     125                // A little extra JS for the Notify button
     126                add_action('admin_head', array($this, 'action_admin_head_notify_js'));
    128127                // Manage Posts
    129128                add_filter('post_row_actions', array($this, 'filter_post_row_actions'), 10, 2);
     
    137136            add_filter('pp_notification_auto_subscribe_current_user', array($this, 'filter_pp_notification_auto_subscribe_current_user'), 10, 2);
    138137
     138            add_action('save_post', array($this, 'action_save_post'), 10);
     139
    139140            // Ajax for saving notification updates
    140             add_action('wp_ajax_save_notifications', array($this, 'ajax_save_post_subscriptions'));
    141141            add_action('wp_ajax_pp_notifications_user_post_subscription', array($this, 'handle_user_post_subscription'));
    142142
     
    152152        public function install()
    153153        {
    154 
     154            // Considering we could be moving from Edit Flow, we need to migrate the following users.
     155            $this->migrateLegacyFollowingTerms();
    155156        }
    156157
     
    192193                $publishpress->update_module_option($this->module->name, 'loaded_once', true);
    193194            }
     195
     196            if (version_compare($previous_version, '1.10', '<=')) {
     197                $this->migrateLegacyFollowingTerms();
     198            }
     199        }
     200
     201
     202        protected function migrateLegacyFollowingTerms()
     203        {
     204            global $wpdb;
     205
     206            // Migrate Following Users
     207            $query = "UPDATE {$wpdb->prefix}term_taxonomy SET taxonomy = '{$this->notify_user_taxonomy}' WHERE taxonomy = 'following_users'";
     208            $wpdb->query($query);
    194209        }
    195210
     
    216231            );
    217232
    218             register_taxonomy($this->following_users_taxonomy, $supported_post_types, $args);
     233            register_taxonomy($this->notify_user_taxonomy, $supported_post_types, $args);
     234            register_taxonomy($this->notify_role_taxonomy, $supported_post_types, $args);
    219235        }
    220236
     
    230246            if ($this->is_whitelisted_functional_view())
    231247            {
    232                 wp_enqueue_script('jquery-listfilterizer');
    233                 wp_enqueue_script('jquery-quicksearch');
    234248                wp_enqueue_script(
    235249                    'publishpress-notifications-js',
     
    237251                    array(
    238252                        'jquery',
    239                         'jquery-listfilterizer',
    240                         'jquery-quicksearch',
    241253                    ),
    242254                    PUBLISHPRESS_VERSION,
    243255                    true
    244256                );
     257
     258                wp_enqueue_script('publishpress-chosen-js', PUBLISHPRESS_URL . '/common/libs/chosen/chosen.jquery.js',
     259                    ['jquery'], PUBLISHPRESS_VERSION);
    245260            }
    246261        }
     
    264279                    PUBLISHPRESS_VERSION
    265280                );
    266             }
    267         }
    268 
    269         /**
    270          * JS required for the Follow link to work
     281
     282                wp_enqueue_style('publishpress-chosen-css', PUBLISHPRESS_URL . '/common/libs/chosen/chosen.css', false,
     283                    PUBLISHPRESS_VERSION);
     284            }
     285        }
     286
     287        /**
     288         * JS required for the Notify link to work
    271289         *
    272290         * @since 0.8
    273291         */
    274         public function action_admin_head_follow_js()
     292        public function action_admin_head_notify_js()
    275293        {
    276294            ?>
     
    279297                    $(document).ready(function ($) {
    280298                        /**
    281                          * Action to Follow / Unfollow posts on the manage posts screen
     299                         * Action to Notify / Stop Notifying posts on the manage posts screen
    282300                         */
    283                         $('.wp-list-table, #pp-calendar-view, #pp-story-budget-wrap').on('click', '.pp_follow_link a', function (e) {
     301                        $('.wp-list-table, #pp-calendar-view, #pp-story-budget-wrap').on('click', '.pp_notify_link a', function (e) {
    284302
    285303                            e.preventDefault();
     
    309327
    310328        /**
    311          * Add a "Follow" link to supported post types Manage Posts view
     329         * Add a "Notify" link to supported post types Manage Posts view
    312330         *
    313331         * @since 0.8
     
    331349            }
    332350
    333             $parts                     = $this->get_follow_action_parts($post);
    334             $actions['pp_follow_link'] = '<a title="' . esc_attr($parts['title']) . '" href="' . esc_url($parts['link']) . '">' . $parts['text'] . '</a>';
     351            $parts                     = $this->get_notify_action_parts($post);
     352            $actions['pp_notify_link'] = '<a title="' . esc_attr($parts['title']) . '" href="' . esc_url($parts['link']) . '">' . $parts['text'] . '</a>';
    335353
    336354            return $actions;
     
    338356
    339357        /**
    340          * Get an action parts for a user to follow or unfollow a post
     358         * Get an action parts for a user to set Notify or Stop Notify for a post
    341359         *
    342360         * @since 0.8
    343361         */
    344         private function get_follow_action_parts($post)
     362        private function get_notify_action_parts($post)
    345363        {
    346364            $args = array(
     
    349367            );
    350368
    351             $following_users = $this->get_following_users($post->ID);
    352 
    353             if (in_array(wp_get_current_user()->user_login, $following_users))
    354             {
    355                 $args['method'] = 'unfollow';
     369            $user_to_notify = $this->get_users_to_notify($post->ID);
     370
     371            if (in_array(wp_get_current_user()->user_login, $user_to_notify))
     372            {
     373                $args['method'] = 'stop_notifying';
    356374                $title_text     = __('Click to stop being notified on updates for this post', 'publishpress');
    357                 $follow_text    = __('Stop notifying me', 'publishpress');
     375                $link_text      = __('Stop notifying me', 'publishpress');
    358376            } else
    359377            {
    360                 $args['method'] = 'follow';
     378                $args['method'] = 'start_notifying';
    361379                $title_text     = __('Click to start being notified on updates for this post', 'publishpress');
    362                 $follow_text    = __('Notify me', 'publishpress');
     380                $link_text      = __('Notify me', 'publishpress');
    363381            }
    364382
     
    368386            return array(
    369387                'title' => $title_text,
    370                 'text'  => $follow_text,
     388                'text'  => $link_text,
    371389                'link'  => add_query_arg($args, admin_url('admin-ajax.php')),
    372390            );
     
    383401            }
    384402
    385             $usergroup_post_types = $this->get_post_types_for_module($this->module);
    386             foreach ($usergroup_post_types as $post_type)
     403            $role_post_types = $this->get_post_types_for_module($this->module);
     404            foreach ($role_post_types as $post_type)
    387405            {
    388406                add_meta_box(
     
    391409                    array($this, 'notifications_meta_box'),
    392410                    $post_type,
    393                     'advanced'
     411                    'side',
     412                    'high'
    394413                );
    395414            }
     
    397416
    398417        /**
    399          * Outputs box used to subscribe users and usergroups to Posts
     418         * Outputs box used to subscribe users and roles to Posts
    400419         *
    401420         * @todo add_cap to set subscribers for posts; default to Admin and editors
     
    406425
    407426            ?>
    408             <div id="pp-post_following_box">
     427            <div id="pp_post_notify_box">
    409428                <a name="subscriptions"></a>
    410429
    411                 <p><?php _e('Select the users and user groups that should receive notifications when the status of this post is updated or when an editorial comment is added.', 'publishpress'); ?>
     430                <p>
     431                    <?php _e('Select the users and roles that should receive notifications by workflows.', 'publishpress'); ?>
    412432                </p>
    413                 <div id="pp-post_following_users_box">
    414                     <h4><?php _e('Users', 'publishpress'); ?></h4>
     433
     434                <div id="pp_post_notify_users_box">
    415435                    <?php
    416                     $followers        = $this->get_following_users($post->ID, 'id');
     436                    $users_to_notify        = $this->get_users_to_notify($post->ID, 'id');
     437                    $roles_to_notify        = $this->get_roles_to_notify($post->ID, 'slugs');
     438
     439                    $selected = array_merge($users_to_notify, $roles_to_notify);
     440
    417441                    $select_form_args = array(
    418                         'list_class' => 'pp-post_following_list',
     442                        'list_class' => 'pp_post_notify_list',
    419443                    );
    420                     $this->users_select_form($followers, $select_form_args);
     444                    $this->users_select_form($selected , $select_form_args);
    421445                    ?>
     446
     447
    422448                </div>
    423449
    424                 <?php if ($this->module_enabled('user_groups') && in_array($this->get_current_post_type(), $this->get_post_types_for_module($publishpress->user_groups->module))): ?>
    425                     <div id="pp-post_following_usergroups_box">
    426                         <h4><?php _e('User Groups', 'publishpress') ?></h4>
    427                         <?php
    428                         $following_usergroups = $this->get_following_usergroups($post->ID, 'ids');
    429                         $publishpress->user_groups->usergroups_select_form($following_usergroups);
    430                         ?>
    431                     </div>
    432                 <?php endif; ?>
     450                <p>
     451                    <a href="https://publishpress.com/docs/notifications/"><?php _e('Click here to read more about notifications...', 'publishpress'); ?></a>
     452                </p>
    433453
    434454                <div class="clear"></div>
    435455
    436                 <input type="hidden" name="pp-save_followers" value="1"/> <?php // Extra protection against autosaves
     456                <input type="hidden" name="pp_save_notify" value="1"/> <?php // Extra protection against autosaves
    437457                ?>
    438458
    439                 <?php wp_nonce_field('save_user_usergroups', 'pp_notifications_nonce', false); ?>
     459                <?php wp_nonce_field('save_roles', 'pp_notifications_nonce', false); ?>
    440460            </div>
    441461
     
    443463        }
    444464
    445         /**
    446          * Called when a notification editorial metadata checkbox is checked. Handles saving of a user/usergroup to a post.
    447          */
    448         public function ajax_save_post_subscriptions()
    449         {
    450             global $publishpress;
    451 
    452             // Verify nonce
    453             if (!wp_verify_nonce($_POST['_nonce'], 'save_user_usergroups'))
    454             {
    455                 die(__("Nonce check failed. Please ensure you can add users or user groups to a post.", 'publishpress'));
    456             }
    457 
    458             $post_id            = (int )$_POST['post_id'];
    459             $post               = get_post($post_id);
    460             $user_usergroup_ids = array_map('intval', $_POST['user_group_ids']);
    461             if ((!wp_is_post_revision($post_id) && !wp_is_post_autosave($post_id)) && current_user_can($this->edit_post_subscriptions_cap))
    462             {
    463                 if ($_POST['pp_notifications_name'] === 'pp-selected-users[]')
    464                 {
    465                     $this->save_post_following_users($post, $user_usergroup_ids);
    466                 } else if ($_POST['pp_notifications_name'] == 'following_usergroups[]')
    467                 {
    468                     if ($this->module_enabled('user_groups') && in_array(get_post_type($post_id), $this->get_post_types_for_module($publishpress->user_groups->module)))
    469                     {
    470                         $this->save_post_following_usergroups($post, $user_usergroup_ids);
     465        public function action_save_post($postId)
     466        {
     467            if (!isset($_POST['pp_notifications_nonce']) || !wp_verify_nonce($_POST['pp_notifications_nonce'], 'save_roles')) {
     468                return;
     469            }
     470
     471            if (isset($_POST['to_notify'])) {
     472                // Remove current users
     473                $terms = get_the_terms($postId, $this->notify_user_taxonomy);
     474                $users = array();
     475                if (!empty($terms)) {
     476                    foreach ($terms as $term) {
     477                        $users[] = $term->term_id;
    471478                    }
    472479                }
    473             }
    474             die();
     480                wp_remove_object_terms($postId, $users, $this->notify_user_taxonomy);
     481
     482                // Remove current roles
     483                $terms = get_the_terms($postId, $this->notify_role_taxonomy);
     484                $roles = array();
     485                if (!empty($terms)) {
     486                    foreach ($terms as $term) {
     487                        $roles[] = $term->term_id;
     488                    }
     489                }
     490                wp_remove_object_terms($postId, $roles, $this->notify_role_taxonomy);
     491
     492                foreach ($_POST['to_notify'] as $id) {
     493                    if (is_numeric($id)) {
     494                        // User id
     495                        $this->post_set_users_to_notify($postId, (int)$id, true);
     496                    } else {
     497                        // Role name
     498                        $this->post_set_roles_to_notify($postId, $id, true);
     499                    }
     500                }
     501            }
    475502        }
    476503
     
    499526            }
    500527
    501             if ('follow' == $_GET['method'])
    502             {
    503                 $retval = $this->follow_post_user($post, get_current_user_id());
     528            if ('start_notifying' === $_GET['method'])
     529            {
     530                $retval = $this->post_set_users_to_notify($post, get_current_user_id());
    504531            } else
    505532            {
    506                 $retval = $this->unfollow_post_user($post, get_current_user_id());
     533                $retval = $this->post_set_users_stop_notify($post, get_current_user_id());
    507534            }
    508535
     
    512539            }
    513540
    514             $this->print_ajax_response('success', (object )$this->get_follow_action_parts($post));
     541            $this->print_ajax_response('success', (object )$this->get_notify_action_parts($post));
    515542        }
    516543
     
    545572        }
    546573
    547 
    548         /**
    549          * Called when post is saved. Handles saving of user/usergroup followers
     574        /**
     575         * Sets users to be notified for the specified post
    550576         *
    551577         * @param int $post ID of the post
    552578         */
    553         public function save_post_subscriptions($new_status, $old_status, $post)
    554         {
    555             global $publishpress;
    556             // only if has edit_post_subscriptions cap
    557             if ((!wp_is_post_revision($post) && !wp_is_post_autosave($post)) && isset($_POST['pp-save_followers']) && current_user_can($this->edit_post_subscriptions_cap))
    558             {
    559                 $users      = isset($_POST['pp-selected-users']) ? $_POST['pp-selected-users'] : array();
    560                 $usergroups = isset($_POST['following_usergroups']) ? $_POST['following_usergroups'] : array();
    561                 $this->save_post_following_users($post, $users);
    562                 if ($this->module_enabled('user_groups') && in_array($this->get_current_post_type(), $this->get_post_types_for_module($publishpress->user_groups->module)))
    563                 {
    564                     $this->save_post_following_usergroups($post, $usergroups);
    565                 }
    566             }
    567         }
    568 
    569         /**
    570          * Sets users to follow specified post
    571          *
    572          * @param int $post ID of the post
    573          */
    574         public function save_post_following_users($post, $users = null)
     579        public function save_post_notify_users($post, $users = null)
    575580        {
    576581            if (!is_array($users))
     
    579584            }
    580585
    581             // Add current user to following users
     586            // Add current user to notify list
    582587            $user = wp_get_current_user();
    583588            if ($user && apply_filters('pp_notification_auto_subscribe_current_user', true, 'subscription_action'))
     
    586591            }
    587592
    588             // Add post author to following users
     593            // Add post author to notify list
    589594            if (apply_filters('pp_notification_auto_subscribe_post_author', true, 'subscription_action'))
    590595            {
     
    594599            $users = array_unique(array_map('intval', $users));
    595600
    596             $follow = $this->follow_post_user($post, $users, false);
    597         }
    598 
    599         /**
    600          * Sets usergroups to follow specified post
     601            $this->post_set_users_to_notify($post, $users, false);
     602        }
     603
     604        /**
     605         * Sets roles to be notified for the specified post
    601606         *
    602607         * @param int   $post       ID of the post
    603          * @param array $usergroups Usergroups to follow posts
    604          */
    605         public function save_post_following_usergroups($post, $usergroups = null)
    606         {
    607             if (!is_array($usergroups))
    608             {
    609                 $usergroups = array();
    610             }
    611             $usergroups = array_map('intval', $usergroups);
    612 
    613             $follow = $this->follow_post_usergroups($post, $usergroups, false);
     608         * @param array $roles   Roles to be notified for posts
     609         */
     610        public function save_post_notify_roles($post, $roles = null)
     611        {
     612            if (!is_array($roles))
     613            {
     614                $roles = array();
     615            }
     616            $roles = array_map('intval', $roles);
     617
     618            $this->add_role_to_notify($post, $roles, false);
    614619        }
    615620
     
    620625        {
    621626            global $publishpress;
     627
    622628
    623629            // Kill switch for notification
     
    678684            //if( $parent_ID ) $parent = get_comment( $parent_ID );
    679685
    680             // Set user to follow post, but make it filterable
     686            // Set user to be notified for a post, but make it filterable
    681687            if (apply_filters('pp_notification_auto_subscribe_current_user', true, 'comment'))
    682688            {
    683                 $this->follow_post_user($post, (int )$current_user->ID);
    684             }
    685 
    686             // Set the post author to follow the post but make it filterable
     689                $this->post_set_users_to_notify($post, (int )$current_user->ID);
     690            }
     691
     692            // Set the post author to be notified for the post but make it filterable
    687693            if (apply_filters('pp_notification_auto_subscribe_post_author', true, 'comment'))
    688694            {
    689                 $this->follow_post_user($post, (int )$post->post_author);
     695                $this->post_set_users_to_notify($post, (int )$post->post_author);
    690696            }
    691697
     
    807813            $recipients = array();
    808814
    809             $usergroup_users = array();
    810             if ($this->module_enabled('user_groups'))
    811             {
    812                 // Get following users and usergroups
    813                 $usergroups = $this->get_following_usergroups($post_id, 'ids');
    814                 foreach ((array )$usergroups as $usergroup_id)
    815                 {
    816                     $usergroup = $publishpress->user_groups->get_usergroup_by('id', $usergroup_id);
    817                     foreach ((array )$usergroup->user_ids as $user_id)
     815            $role_users = array();
     816
     817            // Get users and roles to notify
     818            $roles = $this->get_roles_to_notify($post_id, 'slugs');
     819            foreach ((array )$roles as $role_id)
     820            {
     821                $users = get_users(
     822                    [
     823                        'role' => $role_id,
     824                    ]
     825                );
     826
     827                if (!empty($users)) {
     828                    foreach ($users as $user)
    818829                    {
    819                         $usergroup_user = get_user_by('id', $user_id);
    820                         if ($usergroup_user && is_user_member_of_blog($user_id))
     830                        if (is_user_member_of_blog($user->ID))
    821831                        {
    822                             $usergroup_users[] = $usergroup_user->user_email;
     832                            $role_users[] = $user->user_email;
    823833                        }
    824834                    }
     
    826836            }
    827837
    828             $users = $this->get_following_users($post_id, 'user_email');
     838            $users = $this->get_users_to_notify($post_id, 'user_email');
    829839
    830840            // Merge arrays and filter any duplicates
    831             $recipients = array_merge($authors, $admins, $users, $usergroup_users);
     841            $recipients = array_merge($authors, $admins, $users, $role_users);
    832842            $recipients = array_unique($recipients);
    833843
     
    841851                }
    842852                // Don't send the email to the current user unless we've explicitly indicated they should receive it
    843                 if (false === apply_filters('pp_notification_email_current_user', false) && wp_get_current_user()->user_email == $user_email)
     853                if (false === apply_filters('publishpress_notify_current_user', false) && wp_get_current_user()->user_email == $user_email)
    844854                {
    845855                    unset($recipients[$key]);
     
    861871
    862872        /**
    863          * Set a user or users to follow a post
     873         * Set a user or users to be notified for a post
    864874         *
    865875         * @param int|object   $post   Post object or ID
    866876         * @param string|array $users  User or users to subscribe to post updates
    867          * @param bool         $append Whether users should be added to following_users list or replace existing list
     877         * @param bool         $append Whether users should be added to pp_notify_user list or replace existing list
    868878         *
    869879         * @return true|WP_Error     $response  True on success, WP_Error on failure
    870880         */
    871         public function follow_post_user($post, $users, $append = true)
     881        public function post_set_users_to_notify($post, $users, $append = true)
    872882        {
    873883            $post = get_post($post);
     
    883893
    884894            $user_terms = array();
     895
    885896            foreach ($users as $user)
    886897            {
     
    901912
    902913                // Add user as a term if they don't exist
    903                 $term = $this->add_term_if_not_exists($name, $this->following_users_taxonomy);
     914                $term = $this->add_term_if_not_exists($name, $this->notify_user_taxonomy);
    904915
    905916                if (!is_wp_error($term))
     
    908919                }
    909920            }
    910             $set = wp_set_object_terms($post->ID, $user_terms, $this->following_users_taxonomy, $append);
     921
     922            $set = wp_set_object_terms($post->ID, $user_terms, $this->notify_user_taxonomy, $append);
    911923
    912924            if (is_wp_error($set))
     
    920932
    921933        /**
    922          * Removes user from following_users taxonomy for the given Post,
    923          * so they no longer receive future notifications.
    924          *
    925          * @param object           $post  Post object or ID
    926          * @param int|string|array $users One or more users to unfollow from the post
     934         * Set a role or roles to be notified for a post
     935         *
     936         * @param int|object   $post   Post object or ID
     937         * @param string|array $roles  Role or roles to subscribe to post updates
     938         * @param bool         $append Whether roles should be added to pp_notify_role list or replace existing list
     939         *
    927940         * @return true|WP_Error     $response  True on success, WP_Error on failure
    928941         */
    929         public function unfollow_post_user($post, $users)
     942        public function post_set_roles_to_notify($post, $roles, $append = true)
    930943        {
    931944            $post = get_post($post);
     
    935948            }
    936949
     950            if (!is_array($roles))
     951            {
     952                $roles = array($roles);
     953            }
     954
     955            $role_terms = array();
     956
     957            foreach ($roles as $role)
     958            {
     959                $role = get_role($role);
     960
     961                if (!is_object($role))
     962                {
     963                    continue;
     964                }
     965
     966                // Add user as a term if they don't exist
     967                $term = $this->add_term_if_not_exists($role->name, $this->notify_role_taxonomy);
     968
     969                if (!is_wp_error($term))
     970                {
     971                    $role_terms[] = $role->name;
     972                }
     973            }
     974
     975            $set = wp_set_object_terms($post->ID, $role_terms, $this->notify_role_taxonomy, $append);
     976
     977            if (is_wp_error($set))
     978            {
     979                return $set;
     980            } else
     981            {
     982                return true;
     983            }
     984        }
     985
     986        /**
     987         * Removes user from pp_notify_user taxonomy for the given Post,
     988         * so they no longer receive future notifications.
     989         *
     990         * @param object           $post  Post object or ID
     991         * @param int|string|array $users One or more users to stop being notified for the post
     992         * @return true|WP_Error     $response  True on success, WP_Error on failure
     993         */
     994        public function post_set_users_stop_notify($post, $users)
     995        {
     996            $post = get_post($post);
     997            if (!$post)
     998            {
     999                return new WP_Error('missing-post', $this->module->messages['missing-post']);
     1000            }
     1001
    9371002            if (!is_array($users))
    9381003            {
     
    9401005            }
    9411006
    942             $terms = get_the_terms($post->ID, $this->following_users_taxonomy);
     1007            $terms = get_the_terms($post->ID, $this->notify_user_taxonomy);
    9431008            if (is_wp_error($terms))
    9441009            {
     
    9681033                }
    9691034            }
    970             $set = wp_set_object_terms($post->ID, $user_terms, $this->following_users_taxonomy, false);
     1035            $set = wp_set_object_terms($post->ID, $user_terms, $this->notify_user_taxonomy, false);
    9711036
    9721037            if (is_wp_error($set))
     
    9801045
    9811046        /**
    982          * follow_post_usergroups()
    983          *
    984          */
    985         public function follow_post_usergroups($post, $usergroups = 0, $append = true)
    986         {
    987             if (!$this->module_enabled('user_groups'))
    988             {
    989                 return;
    990             }
    991 
     1047         * add_role_to_notify()
     1048         *
     1049         */
     1050        public function add_role_to_notify($post, $roles = 0, $append = true)
     1051        {
    9921052            $post_id = (is_int($post)) ? $post : $post->ID;
    993             if (!is_array($usergroups))
    994             {
    995                 $usergroups = array($usergroups);
    996             }
    997 
    998             // make sure each usergroup id is an integer and not a number stored as a string
    999             foreach ($usergroups as $key => $usergroup)
    1000             {
    1001                 $usergroups[$key] = intval($usergroup);
    1002             }
    1003 
    1004             wp_set_object_terms($post_id, $usergroups, $this->following_usergroups_taxonomy, $append);
     1053            if (!is_array($roles))
     1054            {
     1055                $roles = array($roles);
     1056            }
     1057
     1058            // make sure each role id is an integer and not a number stored as a string
     1059            foreach ($roles as $key => $role)
     1060            {
     1061                $roles[$key] = intval($role);
     1062            }
     1063
     1064            wp_set_object_terms($post_id, $roles, $this->notify_role_taxonomy, $append);
    10051065
    10061066            return;
     
    10081068
    10091069        /**
    1010          * Removes users that are deleted from receiving future notifications (i.e. makes them unfollow posts FOREVER! )
     1070         * Removes users that are deleted from receiving future notifications (i.e. makes them out of notify list for posts FOREVER! )
    10111071         *
    10121072         * @param $id int ID of the user
     
    10241084            if ($user)
    10251085            {
    1026                 // Delete term from the following_users taxonomy
    1027                 $user_following_term = get_term_by('name', $user->user_login, $this->following_users_taxonomy);
    1028                 if ($user_following_term)
    1029                 {
    1030                     wp_delete_term($user_following_term->term_id, $this->following_users_taxonomy);
     1086                // Delete term from the pp_notify_user taxonomy
     1087                $notify_user_term = get_term_by('name', $user->user_login, $this->notify_user_taxonomy);
     1088                if ($notify_user_term)
     1089                {
     1090                    wp_delete_term($notify_user_term->term_id, $this->notify_user_taxonomy);
    10311091                }
    10321092            }
     
    10551115
    10561116        /**
    1057          * Gets a list of the users following the specified post
     1117         * Gets a list of the users to be notified for the specified post
    10581118         *
    10591119         * @param int    $post_id The ID of the post
    10601120         * @param string $return  The field to return
    1061          * @return array $users Users following the specified posts
    1062          */
    1063         public function get_following_users($post_id, $return = 'user_login')
    1064         {
    1065 
    1066             // Get following_users terms for the post
    1067             $users = wp_get_object_terms($post_id, $this->following_users_taxonomy, array('fields' => 'names'));
    1068 
    1069             // Don't have any following users
     1121         * @return array $users Users to notify for the specified posts
     1122         */
     1123        public function get_users_to_notify($post_id, $return = 'user_login')
     1124        {
     1125            // Get pp_notify_user terms for the post
     1126            $users = wp_get_object_terms($post_id, $this->notify_user_taxonomy, array('fields' => 'names'));
     1127
     1128            // Don't have any users to notify
    10701129            if (!$users || is_wp_error($users))
    10711130            {
     
    11241183
    11251184        /**
    1126          * Gets a list of the usergroups that are following specified post
     1185         * Gets a list of the roles that should be notified for the specified post
    11271186         *
    11281187         * @param int $post_id
    1129          * @return array $usergroups All of the usergroup slugs
    1130          */
    1131         public function get_following_usergroups($post_id, $return = 'all')
     1188         * @return array $roles All of the role slugs
     1189         */
     1190        public function get_roles_to_notify($post_id, $return = 'all')
    11321191        {
    11331192            global $publishpress;
     
    11421201            }
    11431202
    1144             $usergroups = wp_get_object_terms($post_id, $this->following_usergroups_taxonomy, array('fields' => $fields));
     1203            $roles = wp_get_object_terms($post_id, $this->notify_role_taxonomy, array('fields' => $fields));
    11451204
    11461205            if ($return == 'slugs')
    11471206            {
    11481207                $slugs = array();
    1149                 foreach ($usergroups as $usergroup)
    1150                 {
    1151                     $slugs[] = $usergroup->slug;
    1152                 }
    1153                 $usergroups = $slugs;
    1154             }
    1155 
    1156             return $usergroups;
    1157         }
    1158 
    1159         /**
    1160          * Gets a list of posts that a user is following
     1208                foreach ($roles as $role)
     1209                {
     1210                    $slugs[] = $role->slug;
     1211                }
     1212                $roles = $slugs;
     1213            }
     1214
     1215            return $roles;
     1216        }
     1217
     1218        /**
     1219         * Gets a list of posts that a user is selected to be notified
    11611220         *
    11621221         * @param string|int $user user_login or id of user
    11631222         * @param array      $args
    1164          * @return array $posts Posts a user is following
    1165          */
    1166         public function get_user_following_posts($user = 0, $args = null)
     1223         * @return array $posts Posts a user is selected to be notified
     1224         */
     1225        public function get_user_to_notify_posts($user = 0, $args = null)
    11671226        {
    11681227            if (!$user)
     
    11791238                'tax_query'      => array(
    11801239                    array(
    1181                         'taxonomy' => $this->following_users_taxonomy,
     1240                        'taxonomy' => $this->notify_user_taxonomy,
    11821241                        'field'    => 'slug',
    11831242                        'terms'    => $user,
     
    11891248                'post_status'    => 'any',
    11901249            );
    1191             $post_args = apply_filters('pp_user_following_posts_query_args', $post_args);
     1250            $post_args = apply_filters('pp_user_to_notify_posts_query_args', $post_args);
    11921251            $posts     = get_posts($post_args);
    11931252
     
    15281587        public function send_notification_comment($args)
    15291588        {
    1530 
    1531 
    15321589            /* translators: 1: blog name, 2: post title */
    15331590            $subject = sprintf(__('[%1$s] New Editorial Comment: "%2$s"', 'publishpress'), $args['blogname'], $args['post_title']);
  • publishpress/trunk/modules/settings/settings.php

    r1827070 r1839664  
    165165            <div class="publishpress-admin pressshack-admin-wrapper wrap">
    166166                <header>
    167                     <h1 class="pressshack-title">
    168                         <a href="//wordpress.org/plugins/publishpress" target="_blank" rel="noopener noreferrer" title="PublishPress">
    169                             <?php _e('PublishPress', 'publishpress') ?>
    170                         </a>
    171                     </h1>
     167                    <h1 class="wp-heading-inline"><?php echo $current_module->title; ?></h1>
    172168
    173169                    <?php echo !empty($display_text) ? $display_text : ''; ?>
     
    344340
    345341            foreach ($_POST['publishpress_module_name'] as $moduleSlug) {
    346                 $module_name = sanitize_key( PublishPress\Util::sanitize_module_name( $moduleSlug ) );
     342                $module_name = sanitize_key( PublishPress\Legacy\Util::sanitize_module_name( $moduleSlug ) );
    347343
    348344                if ($_POST['action'] != 'update'
  • publishpress/trunk/modules/user-groups/lib/user-groups.css

    r1827070 r1839664  
    11/** Post subscriptions **/
    2 .pp-post_following_list {
     2.pp_post_notify_list {
    33}
    44
    5 .pp-post_following_list li {
     5.pp_post_notify_list li {
    66    padding: 10px 5px 5px 5px;
    77    margin: 0;
     
    99}
    1010
    11 .pp-post_following_list li:hover {
     11.pp_post_notify_list li:hover {
    1212    background: #EAF2FA;
    1313}
    1414
    15 .pp-post_following_list li input {
     15.pp_post_notify_list li input {
    1616    float: right;
    1717}
    1818
    19 .pp-post_following_list .pp-user_displayname,
    20 .pp-post_following_list .pp-usergroup_name {
     19.pp_post_notify_list .pp-user_displayname,
     20.pp_post_notify_list .pp-usergroup_name {
    2121    display: block;
    2222    font-size: 14px;
    2323}
    2424
    25 .pp-post_following_list .pp-user_useremail,
    26 .pp-post_following_list .pp-usergroup_description {
     25.pp_post_notify_list .pp-user_useremail,
     26.pp_post_notify_list .pp-usergroup_description {
    2727    display: block;
    2828    color: #ccc;
     
    3030}
    3131
    32 #pp-post_following_box {
     32#pp_post_notify_box {
    3333    margin: 10px 0;
    3434}
    3535
    36 #pp-post_following_box h4 {
     36#pp_post_notify_box h4 {
    3737    background: #F1F1F1;
    3838    font-weight: bold;
     
    4343}
    4444
    45 #pp-post_following_box label.pp-select_all_box {
     45#pp_post_notify_box label.pp-select_all_box {
    4646    float: right;
    4747    margin: -20px 10px;
    4848}
    4949
    50 #pp-post_following_box label.pp-select_all_box input {
     50#pp_post_notify_box label.pp-select_all_box input {
    5151    margin-bottom: 5px;
    5252}
    5353
    54 #pp-post_following_users_box,
    55 #pp-post_following_usergroups_box {
    56     width: 49%;
    57 }
    58 
    59 #pp-post_following_users_box {
    60     float: left;
    61     margin-right: 2%;
    62 }
    63 
    64 #pp-post_following_usergroups_box {
    65     float: right;
    66 }
    67 
    68 .pp-post_following_list {
     54.pp_post_notify_list {
    6955    max-height: 500px !important;
    7056    overflow: auto !important;
    7157    margin-bottom: 0;
    7258}
    73 
    74 #pp-post_following_users_box .list-filterizer-tools,
    75 #pp-post_following_usergroups_box .list-filterizer-tools {
    76     margin-top: 5px;
    77 }
    78 
    79 /** User Groups **/
    80 #profile-page #post_following_usergroups {
    81     width: 300px;
    82 }
    83 
    84 #pp-usergroup-users form.quicksearch,
    85 #pp-post_following_users_box form.quicksearch {
    86     display: none;
    87 }
    88 
    89 #pp-usergroup-users h4 {
    90     margin-top: 0;
    91 }
    92 
    93 .list-filterizer-tabs li {
    94     color: #655997;
    95 }
    96 
    97 .list-filterizer-tabs li.active,
    98 .list-filterizer-tabs li:hover {
    99     background: #655997;
    100     border-color: #655997;
    101     color: #fff;
    102 }
    103 
    104 @media (max-width: 767px) {
    105 
    106     #pp-post_following_usergroups_box,
    107     #pp-post_following_users_box {
    108         float: none;
    109         width: 100%;
    110     }
    111 
    112     #pp-post_following_users_box {
    113         margin-right: 0;
    114         margin-bottom: 20px;
    115     }
    116 }
  • publishpress/trunk/modules/user-groups/user-groups.php

    r1827070 r1839664  
    3232 * class PP_User_Groups
    3333 *
    34  * @todo all of them PHPdocs
    35  * @todo Resolve whether the notifications component of this class should be moved to "subscriptions"
    36  * @todo Decide whether it's functional to store user_ids in the term description array
    37  * - Argument against: it's going to be expensive to look up usergroups for a user
    38  *
     34 * @todo Remove this module. It is deprecated.
    3935 */
    4036
    4137if (!class_exists('PP_User_Groups'))
    4238{
     39    /**
     40     * Class PP_User_Groups
     41     *
     42     * @deprecated
     43     */
    4344    class PP_User_Groups extends PP_Module
    4445    {
     
    593594                                <?php
    594595                                $select_form_args = array(
    595                                     'list_class' => 'pp-post_following_list',
     596                                    'list_class' => 'pp_post_notify_list',
    596597                                    'input_id'   => 'usergroup_users',
    597598                                );
     
    882883            // before <tag>, after <tag>, class, id names?
    883884            $defaults = array(
    884                 'list_class' => 'pp-post_following_list',
     885                'list_class' => 'pp_post_notify_list',
    885886                'list_id'    => 'pp-following_usergroups',
    886887                'input_id'   => 'following_usergroups',
     
    948949        public function get_usergroups($args = array())
    949950        {
    950 
    951951            // We want empty terms by default
    952952            if (!isset($args['hide_empty']))
     
    12591259                foreach ($all_usergroups as $usergroup)
    12601260                {
    1261                     // Not in this usergroup, so keep going
     1261                    // Not in this user group, so keep going
     1262                    if (!isset($usergroup->user_ids) || empty($usergroup->user_ids || !is_array($usergroup->user_ids))) {
     1263                        continue;
     1264                    }
     1265
    12621266                    if (!in_array($user_id, $usergroup->user_ids))
    12631267                    {
  • publishpress/trunk/publishpress.php

    r1827070 r1839664  
    66 * Author: PublishPress
    77 * Author URI: https://publishpress.com
    8  * Version: 1.10.0
     8 * Version: 1.11.0
    99 * Text Domain: publishpress
    1010 * Domain Path: /languages
     
    137137        foreach ($roles as $role => $caps)
    138138        {
    139             PublishPress\Util::add_caps_to_role($role, $caps);
    140         }
    141 
    142         // User groups
     139            PublishPress\Legacy\Util::add_caps_to_role($role, $caps);
     140        }
     141
     142        // Additional capabilities
    143143        $roles = array(
    144             'administrator' => array('edit_usergroups'),
     144            'administrator' => array(apply_filters('pp_manage_roles_cap', 'pp_manage_roles')),
    145145        );
    146146
    147147        foreach ($roles as $role => $caps)
    148148        {
    149             PublishPress\Util::add_caps_to_role($role, $caps);
     149            PublishPress\Legacy\Util::add_caps_to_role($role, $caps);
    150150        }
    151151    }
     
    222222        if (!class_exists('PP_Module'))
    223223        {
    224             require_once(PUBLISHPRESS_ROOT . '/common/php/class-module.php');
     224            require_once(PUBLISHPRESS_BASE_PATH . '/common/php/class-module.php');
    225225        }
    226226
    227227        // Scan the modules directory and include any modules that exist there
    228         // $module_dirs = scandir(PUBLISHPRESS_ROOT . '/modules/');
     228        // $module_dirs = scandir(PUBLISHPRESS_BASE_PATH . '/modules/');
    229229        $default_module_dirs = array(
    230             'modules-settings'       => PUBLISHPRESS_ROOT,
    231             'calendar'               => PUBLISHPRESS_ROOT,
    232             'editorial-metadata'     => PUBLISHPRESS_ROOT,
    233             'notifications'          => PUBLISHPRESS_ROOT,
    234             'content-overview'       => PUBLISHPRESS_ROOT,
    235             'custom-status'          => PUBLISHPRESS_ROOT,
    236             'user-groups'            => PUBLISHPRESS_ROOT,
    237             'improved-notifications' => PUBLISHPRESS_ROOT,
    238             'async-notifications'    => PUBLISHPRESS_ROOT,
     230            'modules-settings'       => PUBLISHPRESS_BASE_PATH,
     231            'calendar'               => PUBLISHPRESS_BASE_PATH,
     232            'editorial-metadata'     => PUBLISHPRESS_BASE_PATH,
     233            'notifications'          => PUBLISHPRESS_BASE_PATH,
     234            'content-overview'       => PUBLISHPRESS_BASE_PATH,
     235            'custom-status'          => PUBLISHPRESS_BASE_PATH,
     236            'roles'                  => PUBLISHPRESS_BASE_PATH,
     237            'improved-notifications' => PUBLISHPRESS_BASE_PATH,
     238            'async-notifications'    => PUBLISHPRESS_BASE_PATH,
    239239
    240240            // @TODO: Move for settings, and remove after cleanup
    241             'dashboard'              => PUBLISHPRESS_ROOT,
    242             'editorial-comments'     => PUBLISHPRESS_ROOT,
    243             'settings'               => PUBLISHPRESS_ROOT,
    244             'efmigration'            => PUBLISHPRESS_ROOT,
     241            'dashboard'              => PUBLISHPRESS_BASE_PATH,
     242            'editorial-comments'     => PUBLISHPRESS_BASE_PATH,
     243            'settings'               => PUBLISHPRESS_BASE_PATH,
     244            'efmigration'            => PUBLISHPRESS_BASE_PATH,
    245245        );
    246246
     
    249249
    250250        // Add add-ons as the last tab
    251         $module_dirs['addons'] = PUBLISHPRESS_ROOT;
     251        $module_dirs['addons'] = PUBLISHPRESS_BASE_PATH;
    252252
    253253        $class_names = array();
     
    280280
    281281        // Other utils
    282         require_once(PUBLISHPRESS_ROOT . '/common/php/util.php');
     282        require_once(PUBLISHPRESS_BASE_PATH . '/common/php/util.php');
    283283
    284284        // Instantiate all of our classes onto the PublishPress object
     
    288288            if (class_exists($class_name))
    289289            {
    290                 $slug        = PublishPress\Util::sanitize_module_name($slug);
     290                $slug        = PublishPress\Legacy\Util::sanitize_module_name($slug);
    291291                $this->$slug = new $class_name();
    292292            }
  • publishpress/trunk/readme.txt

    r1827070 r1839664  
    1 === PublishPress – WordPress Content Calendar and Notification Workflows ===
     1=== PublishPress – PublishPress helps WordPress teams create great content ===
    22Contributors: publishpress, andergmartins, stevejburge, pressshack
    33Author: PublishPress, PressShack
    44Author URI: https://publishpress.com
    5 Tags: Content Calendar, Editorial Calendar, workflow, checklist, pre-publish
     5Tags: Content Calendar, Editorial Calendar, workflow, checklist, permissions
    66Requires at least: 4.6
    77Requires PHP: 5.4
    88Tested up to: 4.9.4
    9 Stable tag: 1.10.0
     9Stable tag: 1.11.0
    1010License: GPLv2 or later
    1111License URI: http://www.gnu.org/licenses/gpl-2.0.html
    1212
    13 PublishPress is the collaboration tool WordPress teams. You get a beautiful editorial calendar and powerful notification workflows.
     13PublishPress is the plugin for WordPress teams. Your team gets an editorial calendar, flexible permissions and notification workflows.
    1414
    1515== Description ==
     
    1919PublishPress is the essential plugin for any WordPress site with multiple team members.
    2020
    21 [Click here to try a free demo of PublishPress](http://publishpress.com/demo)
    22 
    23 PublishPress has multiple tools that help your team stay organized:
    24 
    25 * Use the [Editorial Calendar](https://publishpress.com/docs/calendar/) and [Content Overview](https://publishpress.com/docs/calendar/) to get a clear picture of all your planned and published content.
    26 * You can create [Comments](https://publishpress.com/docs/editorial-comments/) and [Notifications](https://publishpress.com/docs/notifications/) to leave feedback and keep your team in the loop.
     21PublishPress has multiple tools that help your team stay organized when creating content:
     22
     23* Use the [Editorial Calendar](https://publishpress.com/docs/calendar/) and [Content Overview](https://publishpress.com/docs/content-overview/) to get a clear picture of all your planned and published content.
     24* You can write [Comments](https://publishpress.com/docs/editorial-comments/) to leave feedback.
     25* Set up [Notification Workflows](https://publishpress.com/docs/notifications/) to keep your team up-to-date with what’s happening.
    2726* You can add [Metadata](https://publishpress.com/docs/editorial-metadata/) to give your team extra information about each post.
    2827* Create [Custom Statuses](https://publishpress.com/docs/custom-statuses/) so that WordPress matches your team’s workflow.
    2928
     29Interested in finding out more?
     30
     31[Click here to try a free demo of PublishPress](https://publishpress.com/demo/).
     32[Check out premium add-ons](https://publishpress.com/pricing/) for access to all the PublishPress features.
     33
     34
    3035= WHO SHOULD USE PUBLISHPRESS? =
    3136
     
    3439= PREMIUM ADD-ONS FOR PUBLISHPRESS =
    3540
    36 [Content Checklist](https://publishpress.com/addons/content-checklist/): Set high standards for all your published content
    37 [Multiple Authors](https://publishpress.com/addons/multiple-authors/): Easily assign multiple authors to one content item
    38 [Permissions](https://publishpress.com/addons/publishpress-permissions/): Control who gets the click the “Publish” button
    39 [WooCommerce Checklist](https://publishpress.com/addons/woocommerce-checklist/): Set high standards for all your WooCommerce products
    40 [Slack Notifications](https://publishpress.com/addons/publishpress-slack/): Get Slack updates for all content changes
    41 [YouTube](https://publishpress.com/addons/embedpress-youtube/): More features and design options for your YouTube videos
    42 [Wistia](https://publishpress.com/addons/embedpress-wistia/): More features and design options for your Wistia videos
    43 [Vimeo](https://publishpress.com/addons/embedpress-vimeo/): More features and design options  for your Vimeo videos
    44 
    45 [Check out the PublishPress Everything Club](https://publishpress.com/addons/publishpress-club/) for access to all the PublishPress add-ons.
    46 
    47 = EDITORIAL CONTENT CALENDAR =
     41* [Content Checklist](https://publishpress.com/addons/content-checklist/): Set high standards for all your published content
     42* [Multiple Authors](https://publishpress.com/addons/multiple-authors-publishpress/): Easily assign multiple authors to one content item
     43* [Permissions](https://publishpress.com/addons/publishpress-permissions/): Control who gets the click the “Publish” button
     44* [WooCommerce Checklist](https://publishpress.com/addons/woocommerce-checklist/): Set high standards for all your WooCommerce products
     45* [Slack Notifications](https://publishpress.com/addons/publishpress-slack/): Get Slack updates for all content changes
     46
     47[Check out premium add-ons](https://publishpress.com/pricing/) for access to all the PublishPress features.
     48
     49= EDITORIAL CALENDAR =
    4850
    4951The calendar gives you a powerful overview of your publishing schedule. Using the Editorial Calendar, you can easily see when content is planned, and when it was published. You can also drag-and-drop content to a new publication date. By default, you see all the WordPress content you have planned for the next six weeks. If you need to drill down, you can filter the calendar by post status, categories, users or post types.
     
    9193To find the user settings, go to the PublishPress link in your WordPress admin area, and click the “User Groups” tab. By default, PublishPress provides four user groups: Copy Editors, Photographers, Reporters and Section Editors.
    9294
    93 Currently, the most important user of user groups is [Email Notifications](http://publishpress.com/docs/notifications/), but we intend to expand the capabilities of user groups in future PublishPress releases.
    94 
    9595* [Click here for more on PublishPress User Groups](https://publishpress.com/docs/user-groups/)
    9696
     
    103103= I FOUND A BUG, OR WANT TO CONTRIBUTE CODE =
    104104
    105 Great! PublishPress [is available on Github](https://github.com/OSTraining/PublishPress), and we welcome contributions from everyone.
    106 
    107 = ALSO CHECK OUT THE EMBEDPRESS PLUGIN =
    108 
    109 If you like PublishPress, then consider checking out [EmbedPress](https://publishpress.com/embedpress/). The EmbedPress plugin allows you to embed anything in WordPress. Here are some video examples:
    110 
    111 * [How to embed YouTube Videos in WordPress](http://publishpress.com/embedpress/docs/youtube-wordpress/)
    112 * [How to embed Vimeo Videos in WordPress](http://publishpress.com/embedpress/docs/embed-vimeo-video-wordpress/)
    113 * [How to embed Wistia videos in WordPress](https://publishpress.com/embedpress/docs/add-wistia-videos-wordpress/)
    114 
    115 EmbedPress also supports all the Google Drive formats, including these:
    116 
    117 * [How to embed Google Docs in WordPress](http://publishpress.com/embedpress/docs/google-docs-embed-wordpress/)
    118 * [How to embed Google Maps in WordPress](http://publishpress.com/embedpress/docs/google-maps-embed-wordpress/)
    119 * [How to embed Google Sheets in WordPress](http://publishpress.com/embedpress/docs/embed-google-sheets-wordpress/)
    120 
    121 = WORDPRESS TRAINING =
    122 
    123 Visit [OSTraining](https://www.ostraining.com/) to learn from our [WordPress Training](https://www.ostraining.com/wordpress-training/) and read our [best WordPress blog posts](https://www.ostraining.com/blog/wordpress). If you’re interested in a specific WordPress topic, try specific topic areas such as these:
    124 
    125 * [WordPress Development Classes - learn to build plugins](https://www.ostraining.com/classes/wordpress-development)
    126 * [WordPress Theme Design Classes - create your first theme](https://www.ostraining.com/classes/wordpress-themes)
    127 * [WordPress eCommerce Classes - set up a WordPress store](https://www.ostraining.com/classes/wordpress-ecommerce)
     105Great! We’d love to hear from you! PublishPress [is available on Github](https://github.com/OSTraining/PublishPress), and we welcome contributions from everyone.
    128106
    129107== Frequently Asked Questions ==
     
    155133The format is based on [Keep a Changelog](http://keepachangelog.com/)
    156134and this project adheres to [Semantic Versioning](http://semver.org/).
     135
     136= [1.11.0] - 2018-03-13 =
     137
     138*Fixed:*
     139
     140* Fixed workflows and notifications for new posts;
     141* Fixed issue when installed from composer, related to the vendor dir not being found;
     142* Fixed style for icons in the buttons of the popup for iCal subscriptions in the calendar;
     143* Fixed hidden submenus adding basic capabilities after installing for the first time;
     144
     145*Changed:*
     146
     147* Changed the workflow form, adding all fields as required;
     148* Removed support for User Groups - they are deprecated in favor of Roles, in PublishPress;
     149* Moved Notifications metabox to the sidebar with high priority for posts;
     150* Cleaned up UI removing logo from the title in the admin;
     151
     152*Added:*
     153
     154* Added new "From" status: New. Allowing to create workflows specifically from new posts;
     155* Added new submenu for managing Roles;
     156* Added new receiver option for notification workflows to reach Roles;
     157* Added support for multiple Roles per user. A new field is displayed in the user's profile allowing to select multiple roles;
    157158
    158159= [1.10.0] - 2018-02-21 =
  • publishpress/trunk/twig/workflow_help.twig

    r1805300 r1839664  
     1<p>{{ labels.validation_help }}</p>
    12<h3>Content</h3>
    23<p>{{ labels.pre_text }}</p>
  • publishpress/trunk/twig/workflow_metabox.twig

    r1762253 r1839664  
    11<div id="psppno-workflow-metabox" class="pure-g">
    2     <!-- Events -->
     2
     3    <!-- Events -->
    34    {{ section_event|raw }}
    45
  • publishpress/trunk/twig/workflow_receiver_user_field.twig

    r1827070 r1839664  
    77
    88    {% if users %}
    9         <select multiple="multiple" class="{{ list_class }}" name="{{ input_name }}">
     9        <select multiple="multiple" class="{{ list_class }}" name="{{ input_name }}" id="{{ input_id }}">
    1010            {% for user in users %}
    1111                <option value="{{ user.ID }}" {{ selected( user.selected, true ) }}>{{ user.display_name }}</option>
  • publishpress/trunk/vendor/composer/autoload_classmap.php

    r1827070 r1839664  
    77
    88return array(
    9     'WP_Async_Request' => $vendorDir . '/a5hleyrich/wp-background-processing/classes/wp-async-request.php',
    10     'WP_Background_Process' => $vendorDir . '/a5hleyrich/wp-background-processing/classes/wp-background-process.php',
    119);
  • publishpress/trunk/vendor/composer/autoload_psr4.php

    r1827070 r1839664  
    88return array(
    99    'Twig\\' => array($vendorDir . '/twig/twig/src'),
     10    'PublishPress\\Core\\' => array($baseDir . '/core'),
    1011    'PublishPress\\Builder\\' => array($vendorDir . '/publishpress/wordpress-plugin-builder/src'),
    1112    'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
  • publishpress/trunk/vendor/composer/autoload_static.php

    r1827070 r1839664  
    1414        'P' =>
    1515        array (
     16            'PublishPress\\Core\\' => 18,
    1617            'PublishPress\\Builder\\' => 21,
    1718            'Psr\\Container\\' => 14,
     
    2324        array (
    2425            0 => __DIR__ . '/..' . '/twig/twig/src',
     26        ),
     27        'PublishPress\\Core\\' =>
     28        array (
     29            0 => __DIR__ . '/../..' . '/core',
    2530        ),
    2631        'PublishPress\\Builder\\' =>
     
    5156    );
    5257
    53     public static $classMap = array (
    54         'WP_Async_Request' => __DIR__ . '/..' . '/a5hleyrich/wp-background-processing/classes/wp-async-request.php',
    55         'WP_Background_Process' => __DIR__ . '/..' . '/a5hleyrich/wp-background-processing/classes/wp-background-process.php',
    56     );
    57 
    5858    public static function getInitializer(ClassLoader $loader)
    5959    {
     
    6262            $loader->prefixDirsPsr4 = ComposerStaticInit07ee49dc1d4d96922078443d4192a8c4::$prefixDirsPsr4;
    6363            $loader->prefixesPsr0 = ComposerStaticInit07ee49dc1d4d96922078443d4192a8c4::$prefixesPsr0;
    64             $loader->classMap = ComposerStaticInit07ee49dc1d4d96922078443d4192a8c4::$classMap;
    6564
    6665        }, null, ClassLoader::class);
  • publishpress/trunk/vendor/composer/installed.json

    r1827070 r1839664  
    11[
    2     {
    3         "name": "a5hleyrich/wp-background-processing",
    4         "version": "1.0.1",
    5         "version_normalized": "1.0.1.0",
    6         "source": {
    7             "type": "git",
    8             "url": "https://github.com/A5hleyRich/wp-background-processing.git",
    9             "reference": "1f070aab5058dbaf45d5435a343033ddd8a641b1"
    10         },
    11         "dist": {
    12             "type": "zip",
    13             "url": "https://api.github.com/repos/A5hleyRich/wp-background-processing/zipball/1f070aab5058dbaf45d5435a343033ddd8a641b1",
    14             "reference": "1f070aab5058dbaf45d5435a343033ddd8a641b1",
    15             "shasum": ""
    16         },
    17         "require": {
    18             "php": ">=5.2"
    19         },
    20         "time": "2018-02-12T09:24:05+00:00",
    21         "type": "library",
    22         "installation-source": "dist",
    23         "autoload": {
    24             "classmap": [
    25                 "classes/"
    26             ]
    27         },
    28         "notification-url": "https://packagist.org/downloads/",
    29         "license": [
    30             "GPL-2.0-only"
    31         ],
    32         "authors": [
    33             {
    34                 "name": "Ashley Rich",
    35                 "email": "[email protected]"
    36             }
    37         ],
    38         "description": "WP Background Processing can be used to fire off non-blocking asynchronous requests or as a background processing tool, allowing you to queue tasks."
    39     },
    402    {
    413        "name": "pimple/pimple",
     
    143105    {
    144106        "name": "publishpress/wordpress-plugin-builder",
    145         "version": "2.1.1",
    146         "version_normalized": "2.1.1.0",
     107        "version": "2.1.4",
     108        "version_normalized": "2.1.4.0",
    147109        "source": {
    148110            "type": "git",
    149111            "url": "https://github.com/OSTraining/WordPress-Plugin-Builder.git",
    150             "reference": "cde0010cf4aab656db6b7764dcd0d482290718a7"
    151         },
    152         "dist": {
    153             "type": "zip",
    154             "url": "https://api.github.com/repos/OSTraining/WordPress-Plugin-Builder/zipball/cde0010cf4aab656db6b7764dcd0d482290718a7",
    155             "reference": "cde0010cf4aab656db6b7764dcd0d482290718a7",
    156             "shasum": ""
    157         },
    158         "time": "2018-02-13T23:06:08+00:00",
     112            "reference": "6658ad5e35ec32877ee941e3680702bfb86986e5"
     113        },
     114        "dist": {
     115            "type": "zip",
     116            "url": "https://api.github.com/repos/OSTraining/WordPress-Plugin-Builder/zipball/6658ad5e35ec32877ee941e3680702bfb86986e5",
     117            "reference": "6658ad5e35ec32877ee941e3680702bfb86986e5",
     118            "shasum": ""
     119        },
     120        "time": "2018-03-01T22:09:46+00:00",
    159121        "type": "library",
    160122        "installation-source": "dist",
     
    176138        "description": "Base class for WordPress plugin builder",
    177139        "support": {
    178             "source": "https://github.com/OSTraining/WordPress-Plugin-Builder/tree/2.1.1",
     140            "source": "https://github.com/OSTraining/WordPress-Plugin-Builder/tree/2.1.4",
    179141            "issues": "https://github.com/OSTraining/WordPress-Plugin-Builder/issues"
    180142        }
     
    182144    {
    183145        "name": "twig/twig",
    184         "version": "v1.35.0",
    185         "version_normalized": "1.35.0.0",
     146        "version": "v1.35.2",
     147        "version_normalized": "1.35.2.0",
    186148        "source": {
    187149            "type": "git",
    188150            "url": "https://github.com/twigphp/Twig.git",
    189             "reference": "daa657073e55b0a78cce8fdd22682fddecc6385f"
    190         },
    191         "dist": {
    192             "type": "zip",
    193             "url": "https://api.github.com/repos/twigphp/Twig/zipball/daa657073e55b0a78cce8fdd22682fddecc6385f",
    194             "reference": "daa657073e55b0a78cce8fdd22682fddecc6385f",
     151            "reference": "9c24f2cd39dc1906b76879e099970b7e53724601"
     152        },
     153        "dist": {
     154            "type": "zip",
     155            "url": "https://api.github.com/repos/twigphp/Twig/zipball/9c24f2cd39dc1906b76879e099970b7e53724601",
     156            "reference": "9c24f2cd39dc1906b76879e099970b7e53724601",
    195157            "shasum": ""
    196158        },
     
    203165            "symfony/phpunit-bridge": "~3.3@dev"
    204166        },
    205         "time": "2017-09-27T18:06:46+00:00",
     167        "time": "2018-03-03T16:21:29+00:00",
    206168        "type": "library",
    207169        "extra": {
  • publishpress/trunk/vendor/twig/twig/.travis.yml

    r1744962 r1839664  
    99
    1010php:
    11     - 5.3
    1211    - 5.4
    1312    - 5.5
     
    1514    - 7.0
    1615    - 7.1
     16    - 7.2
    1717    - nightly
    1818
    1919env:
    2020    - TWIG_EXT=no
    21     - TWIG_EXT=yes
    2221
    2322before_install:
     
    4140matrix:
    4241    fast_finish: true
    43     exclude:
    44         - php: 7.0
     42    include:
     43        - php: 5.3
     44          dist: precise
    4545          env: TWIG_EXT=yes
    46         - php: 7.1
     46        - php: 5.3
     47          dist: precise
     48          env: TWIG_EXT=no
     49        - php: 5.4
    4750          env: TWIG_EXT=yes
    48         - php: nightly
     51        - php: 5.5
    4952          env: TWIG_EXT=yes
     53        - php: 5.6
     54          env: TWIG_EXT=yes
  • publishpress/trunk/vendor/twig/twig/CHANGELOG

    r1744962 r1839664  
     1* 1.35.2 (2018-03-03)
     2
     3 * fixed a regression in the way the profiler is registered in templates
     4
     5* 1.35.1 (2018-03-02)
     6
     7 * added an exception when using "===" instead of "same as"
     8 * fixed possible array to string conversion concealing actual error
     9 * made variable names deterministic in compiled templates
     10 * fixed length filter when passing an instance of IteratorAggregate
     11 * fixed Environment::resolveTemplate to accept instances of TemplateWrapper
     12
    113* 1.35.0 (2017-09-27)
    214
  • publishpress/trunk/vendor/twig/twig/LICENSE

    r1597614 r1839664  
    1 Copyright (c) 2009-2017 by the Twig Team.
     1Copyright (c) 2009-2018 by the Twig Team.
    22
    33Some rights reserved.
  • publishpress/trunk/vendor/twig/twig/doc/advanced.rst

    r1704384 r1839664  
    801801        public function rot13($value)
    802802        {
    803             return $rot13Provider->rot13($value);
     803            return $this->rot13Provider->rot13($value);
    804804        }
    805805    }
     
    850850        public function rot13($value)
    851851        {
    852             return $rot13Provider->rot13($value);
     852            return $this->rot13Provider->rot13($value);
    853853        }
    854854    }
  • publishpress/trunk/vendor/twig/twig/doc/filters/length.rst

    r1704384 r1839664  
    1515it will return the length of the string provided by that method.
    1616
     17For objects that implement the ``IteratorAggregate`` interface, ``length`` will use the return value of the ``iterator_count()`` method.
     18
    1719.. code-block:: jinja
    1820
  • publishpress/trunk/vendor/twig/twig/doc/filters/replace.rst

    r1704384 r1839664  
    1212       if the foo parameter equals to the foo string. #}
    1313
     14    {# using % as a delimiter is purely conventional and optional #}
     15
     16    {{ "I like this and --that--."|replace({'this': foo, '--that--': "bar"}) }}
     17
     18    {# outputs I like foo and bar #}
     19
    1420Arguments
    1521---------
  • publishpress/trunk/vendor/twig/twig/doc/functions/block.rst

    r1704384 r1839664  
    1919    {% block body %}{% endblock %}
    2020
    21 The ``block`` function can also be used to display one block of another
     21The ``block`` function can also be used to display one block from another
    2222template:
    2323
  • publishpress/trunk/vendor/twig/twig/ext/twig/php_twig.h

    r1744962 r1839664  
    1616#define PHP_TWIG_H
    1717
    18 #define PHP_TWIG_VERSION "1.35.0"
     18#define PHP_TWIG_VERSION "1.35.2"
    1919
    2020#include "php.h"
  • publishpress/trunk/vendor/twig/twig/ext/twig/twig.c

    r1704384 r1839664  
    871871        if (null === $object) {
    872872            $message = sprintf('Impossible to invoke a method ("%s") on a null variable', $item);
     873        } elseif (is_array($object)) {
     874            $message = sprintf('Impossible to invoke a method ("%s") on an array.', $item);
    873875        } else {
    874876            $message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
     
    886888        Z_ADDREF_P(object);
    887889        if (Z_TYPE_P(object) == IS_NULL) {
    888             convert_to_string_ex(&object);
    889 
    890             TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on a %s variable.", item, type_name);
     890            TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on a null variable.", item);
     891        } else if (Z_TYPE_P(object) == IS_ARRAY) {
     892            TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on an array.", item);
    891893        } else {
    892894            convert_to_string_ex(&object);
  • publishpress/trunk/vendor/twig/twig/lib/Twig/Compiler.php

    r1704384 r1839664  
    2626    protected $sourceLine;
    2727    protected $filename;
     28    private $varNameSalt = 0;
    2829
    2930    public function __construct(Twig_Environment $env)
     
    7980        $this->sourceLine = 1;
    8081        $this->indentation = $indentation;
     82        $this->varNameSalt = 0;
    8183
    8284        if ($node instanceof Twig_Node_Module) {
     
    277279    public function getVarName()
    278280    {
    279         return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false));
     281        return sprintf('__internal_%s', hash('sha256', __METHOD__.$this->varNameSalt++));
    280282    }
    281283}
  • publishpress/trunk/vendor/twig/twig/lib/Twig/Environment.php

    r1744962 r1839664  
    1717class Twig_Environment
    1818{
    19     const VERSION = '1.35.0';
    20     const VERSION_ID = 13500;
     19    const VERSION = '1.35.2';
     20    const VERSION_ID = 13501;
    2121    const MAJOR_VERSION = 1;
    2222    const MINOR_VERSION = 35;
    23     const RELEASE_VERSION = 0;
     23    const RELEASE_VERSION = 1;
    2424    const EXTRA_VERSION = '';
    2525
     
    133133        if (is_string($this->originalCache)) {
    134134            $r = new ReflectionMethod($this, 'writeCacheFile');
    135             if ($r->getDeclaringClass()->getName() !== __CLASS__) {
     135            if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
    136136                @trigger_error('The Twig_Environment::writeCacheFile method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED);
    137137
     
    140140
    141141            $r = new ReflectionMethod($this, 'getCacheFilename');
    142             if ($r->getDeclaringClass()->getName() !== __CLASS__) {
     142            if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
    143143                @trigger_error('The Twig_Environment::getCacheFilename method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED);
    144144
     
    563563     * Tries to load a template consecutively from an array.
    564564     *
    565      * Similar to loadTemplate() but it also accepts Twig_TemplateInterface instances and an array
    566      * of templates where each is tried to be loaded.
    567      *
    568      * @param string|Twig_Template|array $names A template or an array of templates to try consecutively
    569      *
    570      * @return Twig_Template
     565     * Similar to loadTemplate() but it also accepts instances of Twig_Template and
     566     * Twig_TemplateWrapper, and an array of templates where each is tried to be loaded.
     567     *
     568     * @param string|Twig_Template|Twig_TemplateWrapper|array $names A template or an array of templates to try consecutively
     569     *
     570     * @return Twig_Template|Twig_TemplateWrapper
    571571     *
    572572     * @throws Twig_Error_Loader When none of the templates can be found
     
    581581        foreach ($names as $name) {
    582582            if ($name instanceof Twig_Template) {
     583                return $name;
     584            }
     585
     586            if ($name instanceof Twig_TemplateWrapper) {
    583587                return $name;
    584588            }
  • publishpress/trunk/vendor/twig/twig/lib/Twig/ExpressionParser.php

    r1704384 r1839664  
    200200                }
    201201
     202                // no break
    202203            default:
    203204                if ($token->test(Twig_Token::PUNCTUATION_TYPE, '[')) {
     
    205206                } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '{')) {
    206207                    $node = $this->parseHashExpression();
     208                } elseif ($token->test(Twig_Token::OPERATOR_TYPE, '=') && ('==' === $this->parser->getStream()->look(-1)->getValue() || '!=' === $this->parser->getStream()->look(-1)->getValue())) {
     209                    throw new Twig_Error_Syntax(sprintf('Unexpected operator of value "%s". Did you try to use "===" or "!==" for strict comparison? Use "is same as(value)" instead.', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext());
    207210                } else {
    208211                    throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s".', Twig_Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext());
     
    314317        while (true) {
    315318            $token = $this->parser->getCurrentToken();
    316             if ($token->getType() == Twig_Token::PUNCTUATION_TYPE) {
     319            if (Twig_Token::PUNCTUATION_TYPE == $token->getType()) {
    317320                if ('.' == $token->getValue() || '[' == $token->getValue()) {
    318321                    $node = $this->parseSubscriptExpression($node);
     
    385388        $arguments = new Twig_Node_Expression_Array(array(), $lineno);
    386389        $type = Twig_Template::ANY_CALL;
    387         if ($token->getValue() == '.') {
     390        if ('.' == $token->getValue()) {
    388391            $token = $stream->next();
    389392            if (
    390                 $token->getType() == Twig_Token::NAME_TYPE
     393                Twig_Token::NAME_TYPE == $token->getType()
    391394                ||
    392                 $token->getType() == Twig_Token::NUMBER_TYPE
     395                Twig_Token::NUMBER_TYPE == $token->getType()
    393396                ||
    394                 ($token->getType() == Twig_Token::OPERATOR_TYPE && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue()))
     397                (Twig_Token::OPERATOR_TYPE == $token->getType() && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue()))
    395398            ) {
    396399                $arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno);
  • publishpress/trunk/vendor/twig/twig/lib/Twig/Extension/Core.php

    r1704384 r1839664  
    662662        if ($start >= 0 && $length >= 0 && $item instanceof Iterator) {
    663663            try {
    664                 return iterator_to_array(new LimitIterator($item, $start, $length === null ? -1 : $length), $preserveKeys);
     664                return iterator_to_array(new LimitIterator($item, $start, null === $length ? -1 : $length), $preserveKeys);
    665665            } catch (OutOfBoundsException $exception) {
    666666                return array();
     
    12171217     * hex entity for the Unicode replacement character.
    12181218     */
    1219     if (($ord <= 0x1f && $chr != "\t" && $chr != "\n" && $chr != "\r") || ($ord >= 0x7f && $ord <= 0x9f)) {
     1219    if (($ord <= 0x1f && "\t" != $chr && "\n" != $chr && "\r" != $chr) || ($ord >= 0x7f && $ord <= 0x9f)) {
    12201220        return '&#xFFFD;';
    12211221    }
     
    12251225     * replace it with while grabbing the hex value of the character.
    12261226     */
    1227     if (strlen($chr) == 1) {
     1227    if (1 == strlen($chr)) {
    12281228        $hex = strtoupper(substr('00'.bin2hex($chr), -2));
    12291229    } else {
     
    12721272        }
    12731273
     1274        if ($thing instanceof \IteratorAggregate) {
     1275            return iterator_count($thing);
     1276        }
     1277
    12741278        return 1;
    12751279    }
     
    13691373        if ($thing instanceof \Countable || is_array($thing)) {
    13701374            return count($thing);
     1375        }
     1376
     1377        if ($thing instanceof \IteratorAggregate) {
     1378            return iterator_count($thing);
    13711379        }
    13721380
     
    14451453 * <pre>
    14461454 * {# evaluates to true if the foo variable is an array or a traversable object #}
    1447  * {% if foo is traversable %}
     1455 * {% if foo is iterable %}
    14481456 *     {# ... #}
    14491457 * {% endif %}
  • publishpress/trunk/vendor/twig/twig/lib/Twig/Lexer.php

    r1704384 r1839664  
    236236
    237237            if ($this->cursor >= $this->end) {
    238                 throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', $this->state === self::STATE_BLOCK ? 'block' : 'variable'), $this->currentVarBlockLine, $this->source);
     238                throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', self::STATE_BLOCK === $this->state ? 'block' : 'variable'), $this->currentVarBlockLine, $this->source);
    239239            }
    240240        }
     
    338338        } elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) {
    339339            list($expect, $lineno) = array_pop($this->brackets);
    340             if ($this->code[$this->cursor] != '"') {
     340            if ('"' != $this->code[$this->cursor]) {
    341341                throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', $expect), $lineno, $this->source);
    342342            }
  • publishpress/trunk/vendor/twig/twig/lib/Twig/Loader/Filesystem.php

    r1704384 r1839664  
    280280        return strspn($file, '/\\', 0, 1)
    281281            || (strlen($file) > 3 && ctype_alpha($file[0])
    282                 && substr($file, 1, 1) === ':'
     282                && ':' === substr($file, 1, 1)
    283283                && strspn($file, '/\\', 2, 1)
    284284            )
  • publishpress/trunk/vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php

    r1704384 r1839664  
    5757            if ($this->inABody) {
    5858                if (!$node instanceof Twig_Node_Expression) {
    59                     if (get_class($node) !== 'Twig_Node') {
     59                    if ('Twig_Node' !== get_class($node)) {
    6060                        array_unshift($this->prependedNodes, array());
    6161                    }
     
    8989                $this->inABody = false;
    9090            } elseif ($this->inABody) {
    91                 if (!$expression && get_class($node) !== 'Twig_Node' && $prependedNodes = array_shift($this->prependedNodes)) {
     91                if (!$expression && 'Twig_Node' !== get_class($node) && $prependedNodes = array_shift($this->prependedNodes)) {
    9292                    $nodes = array();
    9393                    foreach (array_unique($prependedNodes) as $name) {
  • publishpress/trunk/vendor/twig/twig/lib/Twig/Parser.php

    r1704384 r1839664  
    3232    protected $traits;
    3333    protected $embeddedTemplates = array();
     34    private $varNameSalt = 0;
    3435
    3536    public function __construct(Twig_Environment $env)
     
    5051    public function getVarName()
    5152    {
    52         return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false));
     53        return sprintf('__internal_%s', hash('sha256', __METHOD__.$this->varNameSalt++));
    5354    }
    5455
     
    99100        $this->importedSymbols = array(array());
    100101        $this->embeddedTemplates = array();
     102        $this->varNameSalt = 0;
    101103
    102104        try {
     
    154156                    $token = $this->getCurrentToken();
    155157
    156                     if ($token->getType() !== Twig_Token::NAME_TYPE) {
     158                    if (Twig_Token::NAME_TYPE !== $token->getType()) {
    157159                        throw new Twig_Error_Syntax('A block must start with a tag name.', $token->getLine(), $this->stream->getSourceContext());
    158160                    }
     
    384386            }
    385387
    386             throw new Twig_Error_Syntax('A template that extends another one cannot include contents outside Twig blocks. Did you forget to put the contents inside a {% block %} tag?', $node->getTemplateLine(), $this->stream->getSourceContext());
     388            throw new Twig_Error_Syntax('A template that extends another one cannot include content outside Twig blocks. Did you forget to put the content inside a {% block %} tag?', $node->getTemplateLine(), $this->stream->getSourceContext());
    387389        }
    388390
  • publishpress/trunk/vendor/twig/twig/lib/Twig/Profiler/NodeVisitor/Profiler.php

    r1704384 r1839664  
    5656    private function getVarName()
    5757    {
    58         return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false));
     58        return sprintf('__internal_%s', hash('sha256', $this->extensionName));
    5959    }
    6060
  • publishpress/trunk/vendor/twig/twig/lib/Twig/Template.php

    r1704384 r1839664  
    569569            if (null === $object) {
    570570                $message = sprintf('Impossible to invoke a method ("%s") on a null variable.', $item);
     571            } elseif (is_array($object)) {
     572                $message = sprintf('Impossible to invoke a method ("%s") on an array.', $item);
    571573            } else {
    572574                $message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s").', $item, gettype($object), $object);
     
    697699            @trigger_error($message, E_USER_DEPRECATED);
    698700
    699             return $ret === '' ? '' : new Twig_Markup($ret, $this->env->getCharset());
     701            return '' === $ret ? '' : new Twig_Markup($ret, $this->env->getCharset());
    700702        }
    701703
  • publishpress/trunk/vendor/twig/twig/lib/Twig/TokenParser/For.php

    r1704384 r1839664  
    4141        $stream->expect(Twig_Token::BLOCK_END_TYPE);
    4242        $body = $this->parser->subparse(array($this, 'decideForFork'));
    43         if ($stream->next()->getValue() == 'else') {
     43        if ('else' == $stream->next()->getValue()) {
    4444            $stream->expect(Twig_Token::BLOCK_END_TYPE);
    4545            $else = $this->parser->subparse(array($this, 'decideForEnd'), true);
  • publishpress/trunk/vendor/twig/twig/lib/Twig/TokenParserBroker.php

    r1597614 r1839664  
    6262    }
    6363
    64     public function addTokenParserBroker(Twig_TokenParserBroker $broker)
     64    public function addTokenParserBroker(self $broker)
    6565    {
    6666        $this->brokers[] = $broker;
    6767    }
    6868
    69     public function removeTokenParserBroker(Twig_TokenParserBroker $broker)
     69    public function removeTokenParserBroker(self $broker)
    7070    {
    7171        if (false !== $pos = array_search($broker, $this->brokers)) {
  • publishpress/trunk/vendor/twig/twig/lib/Twig/TokenStream.php

    r1704384 r1839664  
    140140    public function isEOF()
    141141    {
    142         return $this->tokens[$this->current]->getType() === Twig_Token::EOF_TYPE;
     142        return Twig_Token::EOF_TYPE === $this->tokens[$this->current]->getType();
    143143    }
    144144
  • publishpress/trunk/vendor/twig/twig/test/Twig/Tests/Extension/SandboxTest.php

    r1744962 r1839664  
    253253        } catch (Exception $e) {
    254254        }
    255         if ($e === null) {
     255        if (null === $e) {
    256256            $this->fail('An exception should be thrown for this test to be valid.');
    257257        }
  • publishpress/trunk/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/child_contents_outside_blocks.test

    r1704384 r1839664  
    11--TEST--
    2 Exception for child templates defining contents outside blocks defined by parent
     2Exception for child templates defining content outside blocks defined by parent
    33--TEMPLATE--
    44{% extends 'base.twig' %}
     
    1313{% endblock %}
    1414--EXCEPTION--
    15 Twig_Error_Syntax: A template that extends another one cannot include contents outside Twig blocks. Did you forget to put the contents inside a {% block %} tag in "index.twig" at line 3?
     15Twig_Error_Syntax: A template that extends another one cannot include content outside Twig blocks. Did you forget to put the content inside a {% block %} tag in "index.twig" at line 3?
  • publishpress/trunk/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/length.test

    r1704384 r1839664  
    77{{ to_string_able|length }}
    88{{ countable|length }}
     9{{ iterator_aggregate|length }}
    910{{ null|length }}
    1011{{ magic|length }}
     
    1718    'to_string_able' => new ToStringStub('foobar'),
    1819    'countable' => new CountableStub(42),       /* also asserts we do *not* call __toString() */
     20    'iterator_aggregate' => new IteratorAggregateStub(array('a', 'b', 'c')),   /* also asserts we do *not* call __toString() */
    1921    'null'          => null,
    2022    'magic'         => new MagicCallStub(),     /* used to assert we do *not* call __call */
     
    27296
    283042
     313
    29320
    30331
  • publishpress/trunk/vendor/twig/twig/test/Twig/Tests/IntegrationTest.php

    r1704384 r1839664  
    308308    }
    309309}
     310
     311/**
     312 * This class is used in tests for the length filter.
     313 */
     314class IteratorAggregateStub implements \IteratorAggregate
     315{
     316    private $data;
     317
     318    public function __construct(array $data)
     319    {
     320        $this->data = $data;
     321    }
     322
     323    public function getIterator()
     324    {
     325        return new ArrayIterator($this->data);
     326    }
     327}
  • publishpress/trunk/vendor/twig/twig/test/Twig/Tests/TemplateTest.php

    r1744962 r1839664  
    5959            array('{{ null.a }}', 'Impossible to access an attribute ("a") on a null variable in "%s" at line 1.'),
    6060            array('{{ null.a() }}', 'Impossible to invoke a method ("a") on a null variable in "%s" at line 1.'),
     61            array('{{ array.a() }}', 'Impossible to invoke a method ("a") on an array in "%s" at line 1.'),
    6162            array('{{ empty_array.a }}', 'Key "a" does not exist as the array is empty in "%s" at line 1.'),
    6263            array('{{ array.a }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1.'),
Note: See TracChangeset for help on using the changeset viewer.