PagePermissions.php 6.89 KB
<?php
/**
 * Public API
 */
class PagePermissions {
    const META = 'accessible_to_roles';
    const OPT  = '';

    const ELE_SEL       = 'general_access';
    const ELE_CUST      = 'roles';
    const ELE_AUTH      = 'message_auth';
    const ELE_CUST_AUTH = 'message_cust_auth';
    const ELE_DENIED    = 'message_cust_denied';

    const OPT_ALL  = 0;
    const OPT_AUTH = 1;
    const OPT_CUST = 2;

    private static $current_user = false;

    public static function init() {
        if (false !== self::$current_user) {
            throw new OverflowException('PagePermissions already initialized');
        }

        self::$current_user = _get_current_user();
    }

    /**
     * @param {Integer} $post_id
     * @returns Boolean
     * @throw InvalidArgumentException
     */
    public static function current_user_can_view($post_id = false) {
        static $settings = false;
        if (false === $settings) {
            $settings = new WP_Option(PagePermissionsAdmin::SETTING_NS);
        }

        if (false === $post_id) {
            global $post;
            $post_id = $post->ID;
        }

        // Meta value hasn't been set, assume public page (maybe should go off WP_Option default instead though...
        if ('' === $data = get_custom_data(self::META, $post_id)) {
            $data = Array(self::ELE_SEL => $settings[self::ELE_SEL], self::ELE_CUST => $settings[self::ELE_CUST]);
        }

        // Anyone has access, God has no limitations
        if ($data[self::ELE_SEL] == self::OPT_ALL || is_site_admin()) {
            return true;
        }

        // Login required and user is logged in
        if ($data[self::ELE_SEL] == self::OPT_AUTH) {
            if (is_user_logged_in()) {
                return true;
            }

            return $settings[self::ELE_AUTH];
        }

        // Specific role required and user meets it
        if ($data[self::ELE_SEL] == self::OPT_CUST) {
            if (!is_user_logged_in()) {
                return $settings[self::ELE_CUST_AUTH];
            }

            if (isset($data[self::ELE_CUST][self::get_user_role()])) {
                return true;
            }

            return $settings[self::ELE_DENIED];
        }

        return 'An unknown permission error has occurred';
    }

    /**
     * @param {Integer|String} $user Username or ID of user to lookup (or false for current user)
     * @returns {String} $role The key of the users' role
     */
    public static function get_user_role($user = false) {
        if (false === $user) {
            $user_data = self::$current_user;
        } else {
            $user_data = new WP_User($user);
        }

        // or should I throw an exception?
        if ($user_data->ID == 0) {
            return '';
        }

        $user_roles = $user_data->roles;
        $user_role  = array_shift($user_roles);

        return $user_role;
    }

    public static function getFieldNames() {
        static $fields = false;
        if (false !== $fields) {
            return $fields;
        }

        $fields = Array();
        $ref    = new ReflectionClass(__CLASS__);
        $consts = $ref->getConstants();
        foreach ($consts as $const => $value) {
            if (substr($const, 0, 4) == 'ELE_') {
                $fields[$const] = $value;
            }
        }

        return $fields;
    }
}

class PagePermissionsAdmin {
    const CAPABILITY  = 'manage_page_permissions';
    const ADMIN_PAGE  = 'page-permission-settings';
    const SUBMIT_HOOK = 'update_def_page_permissions';
    const SETTING_NS  = 'page_permission_defaults';

    public static function make() {
        static $made = false;
        if ($made) {
            throw new OverflowException('make has already beed called');
        }
        $made = true;

        TzTools::import('ClientSettings');

        $role = get_role('administrator');
        $role->add_cap(self::CAPABILITY);

        if (isset($_POST[self::SUBMIT_HOOK]) && current_user_can(self::CAPABILITY)) {
            self::submit();
        }

        add_actions('PagePermissions_Actions');
    }

    public static function viewOptionsPage() {
        $selected = self::getOptions();

        include(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR . 'settings.php');
    }

    public static function viewMetaBox($post, $box_info) {
        $selected = ($post->ID == 0 ? self::getOptions() : get_custom_data(PagePermissions::META, $post->ID));

        if (empty($selected)) {
            $selected = self::getOptions();
        }

        include(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR . 'form.php');
    }

    public static function submit() {
        unset($_POST[self::SUBMIT_HOOK]);

        $options = self::getOptions();
        $fields = PagePermissions::getFieldNames();
        foreach ($fields as $field) {
            if (isset($_POST[$field])) {
                // not sure if stripslashes should go here or in WP_Options
                $options[$field] = stripslashes($_POST[$field]);
            } else {
                $options[$field] = '';
            }
        }

        $options->save();
    }

    private static function getOptions() {
        static $options = false;
        if (false !== $options) {
            return $options;
        }

        $options = new WP_Option(self::SETTING_NS);
        return $options;
    }
}

class PagePermissions_Actions {
    public static function admin_menu() {
        if (current_user_can(ClientSettings::CAPABILITY)) {
            add_submenu_page(ClientSettings::ADMIN_PAGE, 'Permission Defaults', 'Permission Defaults', PagePermissionsAdmin::CAPABILITY, PagePermissionsAdmin::ADMIN_PAGE, Array('PagePermissionsAdmin', 'viewOptionsPage'));
            add_meta_box('page_permissions', 'Page Permissions', Array('PagePermissionsAdmin', 'viewMetaBox'), 'page', 'side', 'low');
        }
    }

    public static function admin_print_scripts() {
        _enqueue_script('page-permissions', plugins_url('PagePermissions.js', __FILE__));
        _localize_script('page-permissions', 'TzPagePermissionsData', Array('trigger' => PagePermissions::ELE_SEL, 'focus' => PagePermissions::OPT_CUST));
    }

    public static function save_post($post_id) {
        if (false === ($real_id = _is_post_revision($post_id))) {
            $real_id = $post_id;
        }
        $current = get_custom_data(PagePermissions::META, $real_id);

        $new = Array();
        $new[PagePermissions::ELE_SEL] = $_POST[PagePermissions::ELE_SEL];
        if (isset($_POST[PagePermissions::ELE_CUST])) {
            $new[PagePermissions::ELE_CUST] = $_POST[PagePermissions::ELE_CUST];
        } else {
            $new[PagePermissions::ELE_CUST] = Array();
        }

        if (empty($current)) {
            add_post_meta($real_id, PagePermissions::META, $new, true);
        } else {
            update_post_meta($real_id, PagePermissions::META, $new);
        }
    }
}

    PagePermissions::init();
    PagePermissionsAdmin::make();
?>