Skip to content

Instantly share code, notes, and snippets.

@lmoffereins
Last active December 20, 2015 23:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lmoffereins/6213466 to your computer and use it in GitHub Desktop.
Save lmoffereins/6213466 to your computer and use it in GitHub Desktop.
Proposal for new Simple History main plugin class
<?php
/**
* The SH_Event Class
*
* @package Simple History
* @subpackage Event
*
* @since 2.0
*/
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! class_exists( 'SH_Event' ) ) :
/**
* SH_Event class
*
* @since 2.0
*/
final class SH_Event {
/**
* Event database ID
*
* @var int
*/
public $db_id;
/**
* Event author ID
*
* @var int
*/
public $event_author = 0;
/**
* Event date in GMT
*
* @var string
*/
public $event_date_gmt = '0000-00-00 00:00:00';
/**
* Event item ID
*
* @var int
*/
public $ID;
/**
* Event item type
*
* Holds the type of the event item, like 'post' or 'category'
*
* @var string
*/
public $event_type = '';
/**
* Event item meta type
*
* Holds the type of the event item type, like 'post_type' or 'taxonomy'
*
* @var string
*/
public $event_meta_type = '';
/**
* Event item name
*
* @var string
*/
public $event_name = '';
/**
* Note on the following event_action and event_action_vars properties:
*
* Those are both taken from the event_action database column. This column
* can hold either just the event action OR an array with the event action
* and its action vars array: array( action, array( var1, var2 ) ). In the
* latter situation the string and vars array will be separated when the
* object is constructed.
*/
/**
* Event item action ID or action string
*
* The action can be one of those:
* - action identifier, will be searched for in global event translation table
* - action string to be filled with vars: 1. type, 2. name, ?. action vars
* - action string as verb as seen in previous setup
*
* NOTE: To get the event action title use {@link SH_Event::get_title()}
*
* @var string
*/
private $event_action = '';
/**
* Event action vars
*
* @var array
*/
private $event_action_vars = array();
/**
* Event item details
*
* @var string|array
*/
public $event_details = '';
/**
* Get an SH_Event by id
*
* @param int $db_id
* @return object SH_Event
*/
public static function get_instance( $db_id ) {
global $wpdb;
// Cast the given id to an integer
$db_id = (int) $db_id;
if ( ! $db_id )
return false;
// Get all data for the given id
$_event = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->simple_history WHERE ID = %d LIMIT 1", $db_id ) );
if ( ! $_event )
return false;
// Return the event as an SH_Event object
return new SH_Event( $_event );
}
/**
* Constructor
*
* @param object $event
*/
public function __construct( $event ) {
foreach ( (array) $event as $key => $value ) {
if ( 'ID' == $key )
$this->db_id = $value;
elseif ( 'event_id' == $key )
$this->ID = $value;
else
$this->$key = $value;
}
// Set the event action
$this->parse_event_action();
}
/**
* Parse the event action
*
* @param string|array $action
*/
public function parse_event_action( $action = '' ) {
if ( empty( $action ) )
$action = $this->event_action;
if ( empty( $action ) )
return;
$action = maybe_unserialize( $action );
// Action is a single string
if ( is_string( $action ) )
$this->event_action = $action;
// Action contains action vars
elseif ( is_array( $action ) && count( $action ) == 2 ) {
// Set the first index as the event action
$this->event_action = $action[0];
// Set the second index as the event action vars
$this->event_action_vars = $action[1];
}
}
/**
* Generate the event title
*
* @return string
*/
public function get_title() {
$sh = simple_history();
// Fetch sentence from the actions table
if ( array_key_exists( $this->event_action, $sh->actions ) )
$action = $sh->actions[ $this->event_action ];
// Action is an actual sentence containing sprintf vars
elseif ( preg_match( "/(%[0-9]*\$?[a-zA-Z])/", $this->event_action ) ) // Search for any %s or %1$s/%2$s/etc.
$action = $this->event_action;
// Action is text to be prepended with <type> and <name>
else
$action = '%1$s %2$s ' . $this->event_action;
// Allow for overwriting the event action string
$action = apply_filters( 'simple_history_event_action', $action, $this );
// Allow filtering for custom action vars line up
$action_vars = apply_filters( 'simple_history_event_action_vars', $this->event_action_vars, $this );
// Prepend event type and name when vars aren't modified
if ( $action_vars == $this->event_action_vars ) {
// Auto-fetch post type or taxonomy label
if ( 'post_type' == $this->event_meta_type )
$label = get_post_type_object( $this->event_type )->labels->singular_name;
elseif ( 'taxonomy' == $this->event_meta_type )
$label = get_taxonomy( $this->event_type )->labels->singular_name;
else
$label = apply_filters( 'simple_history_event_type_label', $this->event_type );
$action_vars = array_unshift( $this->event_action_vars, ucfirst( $label ), ucfirst( $this->event_name ) );
}
// Fill the action string with the event action vars
return vsprintf( $action, $action_vars );
}
/**
* Return event as database safe array
*
* @since 2.0
*
* @return array Event
*/
public function prepare() {
$_event = $this->to_array();
// Reorder event IDs
$_event['ID'] = $this->db_id;
$_event['event_id'] = $this->ID;
unset( $_event['db_id'] );
// Merge event action vars with event action
if ( ! empty( $_event['event_action_vars'] ) )
$_event['event_action'] = array( $_event['event_action'], (array) $_event['event_action_vars'] );
unset( $_event['event_action_vars'] );
$_event = wp_unslash( $_event );
return $_event;
}
/**
* Get the event as an associative array
*
* @since 2.0
*
* @return array
*/
public function to_array() {
// Get the object vars
$event = get_object_vars( $this );
return $event;
}
}
endif; // class_exists
<?php
/**
* Simple History functions
*
* @package Simple History
* @subpackage Functions
*
* @since 2.0
*/
/**
* Register an event
*
* @since 1.1
*
* @uses Simple_History::log_event()
*
* @param array $args Elements that make up the event to register.
* @param boolean $collect Whether to add event to a collection. Default to false.
* @return boolean|WP_Error WP_Error on failure. True on succcess.
*/
function simple_history_add( $args = array(), $collect = false ) {
// Back compat pre-2.0
$depr_message = __('Passing the <code>%s</code> is deprecated. Use <code>%s</code> instead.', 'simple-history');
if ( isset( $args['object_id'] ) ) {
_deprecated_argument( __FUNCTION__, '2.0', sprintf( $depr_message, 'object_id', 'ID' ) );
$args['ID'] = (int) $args['object_id'];
}
if ( isset( $args['object_type'] ) ) {
_deprecated_argument( __FUNCTION__, '2.0', sprintf( $depr_message, 'object_type', 'type' ) );
$args['type'] = $args['object_type'];
}
if ( isset( $args['object_subtype'] ) ) {
_deprecated_argument( __FUNCTION__, '2.0', sprintf( $depr_message, 'object_subtype', 'meta_type' ) );
if ( post_type_exists( $args['object_subtype'] ) ) {
$args['type'] = $args['object_subtype'];
$args['meta_type'] = 'post_type';
} elseif ( taxonomy_exists( $args['object_subtype'] ) ) {
$args['type'] = $args['object_subtype'];
$args['meta_type'] = 'taxonomy';
} else {
$args['meta_type'] = '';
}
}
if ( isset( $args['object_name'] ) ) {
_deprecated_argument( __FUNCTION__, '2.0', sprintf( $depr_message, 'object_name', 'name' ) );
$args['name'] = (int) $args['object_name'];
}
if ( isset( $args['user_id'] ) ) {
_deprecated_argument( __FUNCTION__, '2.0', sprintf( $depr_message, 'user_id', 'author' ) );
$args['author'] = $args['user_id'];
}
if ( isset( $args['description'] ) ) {
_deprecated_argument( __FUNCTION__, '2.0', sprintf( $depr_message, 'description', 'details' ) );
$args['details'] = $args['description'];
}
return simple_history()->log_event( $args, $collect );
}
<?php
/**
* Plugin Name: __Simple History
* Description: A syslog system for WordPress. View all activity/changes on your website.
* Plugin URI: http://eskapism.se/code-playground/simple-history/
* Version: 2.0
* Author: Pär Thernström, Laurens Offereins
* Author URI: http://eskapism.se
* License: GPL2
*/
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! class_exists( 'Simple_History' ) ) :
/**
* Main Simple History Class
*
* @since 2.0
*/
final class Simple_History {
/**
* Holds all events for the current page
* @var array
*/
public $events = array();
/**
* Holds all event action strings
* @var array
*/
public $actions = array();
/**
* Holds all modules
* @var array
*/
public $modules = array();
/**
* The one true Simple History
* @var Simple_History
*/
private static $instance;
/**
* Main Simple History instance
*
* Ensures there's only one instance of Simple_History existing in memory at any
* one time. Also prevents defining globals all over the place.
*
* @since 2.0
*
* @staticvar $instance
* @uses Simple_History::setup_globals() Setup the globals needed
* @uses Simple_History::includes() Include the required files
* @uses Simple_History::setup_actions() Setup the hooks and actions
* @see simple_history()
* @return The one true Simple_History
*/
public static function instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new Simple_History;
self::$instance->setup_globals();
self::$instance->includes();
self::$instance->setup_actions();
}
return self::$instance;
}
/**
* Dummy constructor to prevent Simple_History to be loaded more than once.
*
* @since 2.0
*
* @see Simple_History::instance()
* @see simple_history()
*/
public function __construct() { /* Do nothing here */ }
/**
* Set class default variables
*
* @since 2.0
*/
private function setup_globals() {
/** Versions **********************************************************/
$this->version = '2.0';
$this->db_version = '200';
/** Paths *************************************************************/
$this->file = __FILE__;
$this->basename = plugin_basename( $this->file );
$this->plugin_dir = plugin_dir_path( $this->file );
$this->plugin_url = plugin_dir_url( $this->file );
// Includes
$this->includes_dir = trailingslashit( $this->plugin_dir . 'includes' );
$this->includes_url = trailingslashit( $this->plugin_url . 'includes' );
// Languages
$this->lang_dir = trailingslashit( $this->plugin_dir . 'languages' );
// Modules
$this->modules_dir = trailingslashit( $this->plugin_dir . 'modules' );
$this->modules_url = trailingslashit( $this->plugin_url . 'modules' );
/** Users *************************************************************/
$this->current_user = new stdClass(); // Currently logged in user
$this->view_cap = apply_filters( 'simple_history_view_cap', 'edit_pages' );
$this->sett_cap = apply_filters( 'simple_history_sett_cap', 'manage_options' );
/** Misc **************************************************************/
$this->name = 'Simple History';
$this->domain = 'simple-history';
$this->table = 'simple_history';
/** Cache *************************************************************/
// Add Simple History to global cache groups
wp_cache_add_global_groups( 'simple-history' );
}
/**
* Include required files
*
* @since 2.0
*/
private function includes() {
/** Events ************************************************************/
require( $this->includes_dir . 'classes/class.sh-event.php' );
require( $this->includes_dir . 'install.php' );
require( $this->includes_dir . 'functions.php' );
/** Modules ***********************************************************/
require( $this->includes_dir . 'classes/class.sh-module.php' );
require( $this->includes_dir . 'modules.php' );
/** Admin *************************************************************/
if ( is_admin() ) {
require( $this->includes_dir . 'admin.php' );
}
}
/**
* Set actions and filters
*
* @since 2.0
*/
private function setup_actions() {
// Add actions to plugin activation and deactivation hooks
add_action( 'activate_' . $this->basename, 'simple_history_activation' );
add_action( 'deactivate_' . $this->basename, 'simple_history_deactivation' );
/** Events ************************************************************/
add_action( 'shutdown', array( $this, 'insert_events' ) );
/** Misc **************************************************************/
add_action( 'init', array( $this, 'load_textdomain' ) );
}
/** Public Methods ********************************************************/
/**
* Register an event
*
* Stores the event data in the Simple_History::$events array
*
* @since 2.0
*
* @see simple_history_add()
*
* @param array $args Elements that make up the event to register.
* @param boolean $collect Whether to add this event to a collection of other
* events belonging to the same event item ID.
* @return boolean Whether event registration was successfull.
*/
public function log_event( $args = array(), $collect = true ) {
$defaults = array(
'ID' => 0,
'type' => '',
'meta_type' => '',
'name' => '',
'action' => '',
'action_vars' => array(),
'details' => '',
'author' => '',
);
$args = wp_parse_args( $args, $defaults );
// Require event type, event name and event action
if ( empty( $args['type'] ) )
return new WP_Error('sh_no_event_type', __('Missing event type.', 'simple-history'));
if ( empty( $args['name'] ) )
return new WP_Error('sh_no_event_name', __('Missing event item name.', 'simple-history'));
if ( empty( $args['action'] ) )
return new WP_Error('sh_no_event_action', __('Missing event action.', 'simple-history'));
// Set event date GMT
$args['date_gmt'] = current_time( 'mysql', 1 );
// Find a place to prepend 'event_' to all args...
// Find item of collection
if ( $collect // Do collect
&& 0 != $args['ID'] // Don't do empty ID's
&& $previous = wp_list_filter( $this->events, array(
'ID' => $args['ID'],
'type' => $args['type'],
'meta_type' => $args['meta_type']
) ) // Find matching items on ID, type and meta_type
&& ! empty( $previous ) // Matched items found
) {
// Add event to collection...
// Add new item to list
} else {
$this->events[] = apply_filters( 'simple_history_log_event', $args );
}
return true;
}
/**
* Insert an event in the database
*
* @since 2.0
*
* @param SH_Event|array $event The event object or event data.
* @return int|WP_Error WP_Error on failure. The event database ID on success.
*/
public function insert_event( $event ) {
global $wpdb;
if ( ! is_a( $event, 'SH_Event' ) )
$event = simple_history_get_event( $event );
if ( ! $event || is_wp_error( $event ) )
return $event;
$update = 0 != $event->db_id;
$data = $event->prepare();
// Update existing event
if ( $update ) {
$event_before = simple_history_get_event( $event->db_id );
do_action( 'simple_history_pre_update_event', $event->db_id, $event );
$where = array( 'ID' => $event->db_id );
if ( false === $wpdb->update( $wpdb->simple_history, $data, $where ) ) {
return new WP_Error('db_update_error', __('Could not update event in the database', 'simple-history'), $wpdb->last_error );
}
// Insert new event
} else {
if ( false == $wpdb->insert( $wpdb->simple_history, $data ) ) {
return new WP_Error('db_insert_error', __('Could not insert event into the database', 'simple-history' ), $wpdb->last_error );
}
$event->db_id = (int) $wpdb->insert_id;
}
if ( $update ) {
do_action( 'simple_history_update_event', $event->db_id, $event, $event_before );
} else {
do_action( 'simple_history_insert_event', $event->db_id, $event );
}
return $event->db_id;
}
/**
* Insert registered events in the database
*
* @since 2.0
*
* @uses Simple_History::insert_event() To insert the events
* @return boolean|WP_Error Whether insertion was successfull
*/
public function insert_events() {
if ( empty( $this->events ) )
return true;
foreach ( $this->events as $event ) {
$retval = $this->insert_event( $event );
if ( is_wp_error( $retval ) )
return $retval;
}
return $retval;
}
/**
* Prepare event to be inserted in the database
*
* @since 2.0
*
* @param SH_Event $event Event object
* @return array|WP_Error
*/
public function prepare_event( $event ) {
if ( ! is_a( $event, 'SH_Event' ) )
return new WP_Error('sh_not_an_event', __('Variable to prepare is not an event.', 'simple-history'));
$_event = $event->to_array();
$_event['ID'] = $event->db_id;
$_event['event_id'] = $event->ID;
unset( $_event['db_id'] );
$_event = wp_unslash( $_event );
return apply_filters( 'simple_history_prepare_event', $_event, $event );
}
/**
* Load the translation file for current language. Checks the languages
* folder inside the Simple History plugin first, and then the default
* WordPress languages folder.
*
* Note that custom translation files inside the Simple History plugin
* folder will be removed on Simple History updates. If you're creating
* custom translation files, please use the global language folder.
*
* @since 2.0
*
* @uses apply_filters() Calls 'plugin_locale' with the {@link get_locale()} value
* @uses load_textdomain() To load the textdomain
* @return boolean True on success, false on failure
*/
public function load_textdomain() {
// Traditional WordPress plugin locale filter
$locale = apply_filters( 'plugin_locale', get_locale(), $this->domain );
$mofile = sprintf( '%1$s-%2$s.mo', $this->domain, $locale );
// Setup paths to current locale file
$mofile_local = $this->lang_dir . $mofile;
$mofile_global = WP_LANG_DIR . '/simple-history/' . $mofile;
// Look in global /wp-content/languages/simple-history folder
if ( file_exists( $mofile_global ) ) {
return load_textdomain( $this->domain, $mofile_global );
// Look in local /wp-content/plugins/simple-history/languages/ folder
} elseif ( file_exists( $mofile_local ) ) {
return load_textdomain( $this->domain, $mofile_local );
}
// Nothing found
return false;
}
/**
* Setup the currently logged-in user
*
* @since 2.0
*
* @todo Set anonymous user with comment cookies or bbpress user
* data when available
*
* @uses wp_get_current_user()
*/
public function setup_current_user() {
$this->current_user = &wp_get_current_user();
}
}
/**
* Return the Simple History instance
*
* @since 2.0
*
* @return The one true Simple History instance
*/
function simple_history() {
return Simple_History::instance();
}
// Load this pretty piece of code
simple_history();
endif; // class_exists
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment