Skip to content

Commit

Permalink
First commit of MVP alpha code..
Browse files Browse the repository at this point in the history
  • Loading branch information
mikeschinkel committed May 4, 2015
1 parent a254d11 commit 8dc27c3
Show file tree
Hide file tree
Showing 40 changed files with 5,619 additions and 0 deletions.
1,166 changes: 1,166 additions & 0 deletions globals.php

Large diffs are not rendered by default.

248 changes: 248 additions & 0 deletions includes/class-base.php
@@ -0,0 +1,248 @@
<?php

/**
* Class WPLib_Base
*/
abstract class WPLib_Base {

/**
* @var array Capture any extra $args passed for which there are no properties.
*/
var $extra_args = array();

/**
* @var WPLib_Base|null If not null contains reference to containing object.
*/
var $owner;

/**
* @var bool If true will trigger an error if a non-existent method or property is accessed.
*/
private $_trigger_error = true;

/**
* @param array|string|object $args
*/
function __construct( $args = array() ) {

$this->set_state( $args );

}

/**
* Set the object state given an array of $args with elements that match property names.
*
* @not And array elements not found as properties will be assigned to the property array $this->extra_args.
*
* @param array|object $args
*/
function set_state( $args ) {

$args = wp_parse_args( $args );

foreach ( $args as $name => $value ) {

if ( 'extra_args' != $name && property_exists( $this, $name ) ) {

$this->{$name} = $value;

} else if ( property_exists( $this, $protected_name = "_{$name}" ) ) {

$this->{$protected_name} = $value;

} else {

$this->extra_args[ $name ] = $value;

}

}

}

/**
* Return a class constant for the called instance.
*
* @param string $constant_name
* @param string $class_name
*
* @return mixed|null
*/
function constant( $constant_name, $class_name = null ) {

if ( is_null( $class_name ) ) {

$class_name = get_class( $this );

}

return defined( $constant_ref = "{$class_name}::{$constant_name}" ) ? constant( $constant_ref ) : null;

}

/**
* @param string $action
* @param int $priority
*/
static function add_class_action( $action, $priority = 10 ) {

$hook = "_{$action}" . ( 10 != $priority ? "_{$priority}" : '' );
add_action( $action, array( get_called_class(), $hook ), $priority, 99 );

}

/**
* @param string $filter
* @param int $priority
*/
static function add_class_filter( $filter, $priority = 10 ) {

$hook = "_{$filter}" . ( 10 != $priority ? "_{$priority}" : '' );
add_filter( $filter, array( get_called_class(), $hook ), $priority, 99 );

}

/**
* @param string $action
* @param int $priority
*/
static function remove_class_action( $action, $priority = 10 ) {

$hook = "_{$action}" . ( 10 != $priority ? "_{$priority}" : '' );
remove_action( $action, array( get_called_class(), $hook ), $priority, 99 );

}

/**
* @param string $filter
* @param int $priority
*/
static function remove_class_filter( $filter, $priority = 10 ) {

$hook = "_{$filter}" . ( 10 != $priority ? "_{$priority}" : '' );
remove_filter( $filter, array( get_called_class(), $hook ), $priority, 99 );

}

/**
* @param string $property_name
*
* @return bool
*/
function __isset( $property_name ) {

$save_trigger_error = $this->_trigger_error;
$this->_trigger_error = false;

do { // Use do{}while(false) to allow 'break'ing out of a code sequence.


if ( ! is_callable( array( $this, $property_name ) ) ) {

$isset = false;
break;

}

if ( null === $this->$property_name() ) {

$isset = false;
break;

}

$isset = true;

} while ( false );

$this->_trigger_error = $save_trigger_error;

return $isset;

}

/**
*
* Call same named method to access virtial properties defined as methods.
*
* Generates debugging error message for attempts to get a non-existent property.
*
* @example
*
* $name = $this->name; // If no 'name' property, calls `name()` if that method exists.
*
* @param string $property_name
*
* @return null
*/
function __get( $property_name ) {

$value = null;

if ( is_callable( $callable = array( $this, $property_name ) ) ) {

$value = call_user_func( $callable );

} else if ( $this->_trigger_error ) {

$message = __( "Cannot access property '%s' in class '%s'.", 'wplib' );

WPLib::trigger_error( sprintf( $message, $property_name, get_class( $this ) ) );

$value = null;

}

return $value;

}

/**
* Generate debugging error message for attempts to set a non-existent property.
*
* @param string $property_name
* @param mixed $value
*
* @return void
*/
function __set( $property_name, $value ) {

if ( is_callable( $callable = array( $this, "set_{$property_name}" ) ) ) {

call_user_func( $callable, $value );

} else if ( $this->_trigger_error ) {

$message = __( "Cannot set property '%s' in class '%s'.", 'wplib' );

WPLib::trigger_error( sprintf( $message, $property_name, get_class( $this ) ) );

}

}

/**
* Generate debugging error message for attempts to call a non-existent method.
*
* @param string $method_name
* @param array $args
*
* @return null
*/
function __call( $method_name, $args ) {

$value = null;

if ( $this->_trigger_error ) {

$message = __( "Cannot call method '%s' in class '%s'.", 'wplib' );

WPLib::trigger_error( sprintf( $message, $method_name, get_class( $this ) ) );

}

return $value;

}

}

8 comments on commit 8dc27c3

@wpscholar
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to utilize a PHPDoc notation like WP does to indicate at what version a property, method, function or class was introduced. Example: @since 1.3.0.

I also think we need to utilize a PHPDoc notation like WP does for indicating whether something is public or private (beyond prefixing with an underscore). Example: @access private.

Additionally, as an open source project, we need to be adding the GPL notice to the top of each file.

@mikeschinkel
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to utilize a PHPDoc notation like WP does to indicate at what version a property, method, function or class was introduced...

Agreed. Need your help with figuring out out what to use.

I also think we need to utilize a PHPDoc notation like WP does for indicating whether something is public or private...

Sure. I guess we are going to need to QA steps in the process for things like this.

Additionally, as an open source project, we need to be adding the GPL notice to the top of each file.

WordPress does not do that and StackOverflow thinks we should not.

@tripflex
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I absolutely agree with the @SInCE it has come in handy many times in the past when working with legacy methods.

The way I handled that with PHPStorm was just to add @since @@version in Settings->Editor->File and Code Templates->Includes

For my specific instance I use @@Version because I build out with grunt and use grunt-replace to replace @@Version with the version i'm building with, but figured I would add my 2 cents :) 👍

@mikeschinkel
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tripflex Nice idea. @wpscholar - thoughts?

@wpscholar
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tripflex What was your use case for dynamically generating the version number? I'd be interested in learning more about your build workflow.

@tripflex
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally this is for when i'm deploying any WP plugins I create, and you can actually see one of the open source ones that I just started working on again:

https://github.com/tripflex/wp-login-flow

Specifically you can see in the Gruntfile.js the since replace:

https://github.com/tripflex/wp-login-flow/blob/master/Gruntfile.js#L271

@tripflex
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple reasons I like to have the @SInCE is one for any developers that build off my plugin with another plugin, theme, etc, and this way I know whenever i'm refactoring, updating, or changing things, what version those methods were implemented in. Because I also build off the core of WordPress there are many methods that depend on specific versions of WordPress.

With that in mind whenever I make updates and end up raising the min WordPress version I can go back and look at the last time I raised the min WordPress version, and then check those specific methods that were introduced in that version to hopefully prevent any conflicts or issues, or even make them backwards compatible

@wpscholar
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tripflex Thanks for the details. I could see us implementing something like that as part of the workflow before tagging a new version of the library. cc @mikeschinkel

Please sign in to comment.