Created
August 20, 2018 03:28
-
-
Save danieliser/c90e952aa4fd2a3dcf991a0cf8eb2b6b to your computer and use it in GitHub Desktop.
Simple & reusable PHP counter class & methods add, increase, decrease, subtract, and of course ability to run a callback when the value changes for permanat storage. Includes example usage for WordPress Post types and share count, like counts etc.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/****************************************************************************** | |
* @Copyright (c) 2018, Code Atlantic * | |
******************************************************************************/ | |
if ( ! defined( 'ABSPATH' ) ) { | |
exit; | |
} | |
/** | |
* Class Counter | |
* | |
* @package ForumWP\Model | |
*/ | |
class Counter { | |
/** | |
* @var int | |
*/ | |
private $count = 0; | |
/** | |
* @var null|callable | |
*/ | |
private $callback; | |
/** | |
* @var null|string | |
*/ | |
private $context; | |
/** | |
* Count constructor. | |
* | |
* @param int $count | |
* @param string $context Used to identify what this counters context is. Mainly for passing to generic callbacks to identify which context to save in.s | |
* @param null|callable $callback | |
*/ | |
public function __construct( $count = 0, $context = '', $callback = null ) { | |
$this->context = $context; | |
$this->set( $count ); | |
// Callback is set after the count is stored to prevent unwanted calls to the callback. | |
$this->callback = $callback; | |
return $this; | |
} | |
/** | |
* @param $count | |
*/ | |
public function set( $count ) { | |
$this->count = is_numeric( $count ) ? intval( $count ) : 0; | |
} | |
/** | |
* | |
*/ | |
public function increase() { | |
$this->add(); | |
} | |
/** | |
* @param int $amount | |
*/ | |
public function add( $amount = 1 ) { | |
$this->count = $this->count + intval( $amount ); | |
$this->callback(); | |
} | |
/** | |
* | |
*/ | |
public function decrease() { | |
$this->subtract(); | |
} | |
/** | |
* @param int $amount | |
*/ | |
public function subtract( $amount = 1 ) { | |
if ( $this->count == 0 ) { | |
return; | |
} | |
$new_count = $this->count - intval( $amount ); | |
if ( $new_count < 0 ) { | |
$new_count = 0; | |
} | |
$this->count = $new_count; | |
$this->callback(); | |
} | |
/** | |
* @param $name | |
* @param $value | |
*/ | |
public function __set( $name, $value ) { | |
if ( $name != 'count' ) { | |
$this->$name = $value; | |
return; | |
} | |
$this->count = intval( $value ); | |
$this->callback(); | |
} | |
/** | |
* | |
*/ | |
public function callback() { | |
if ( is_callable( $this->callback ) ) { | |
call_user_func( $this->callback, $this->count, $this->context ); | |
} | |
} | |
/** | |
* @return string | |
*/ | |
public function __toString() { | |
return (string) $this->count; | |
} | |
/** | |
* @param null $key | |
* | |
* @return bool | |
*/ | |
public function __isset( $key = null ) { | |
return (bool) is_numeric( $this->count ); | |
} | |
/** | |
* @return array | |
*/ | |
public function __sleep() { | |
return array( 'count', 'context', 'callback' ); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
if ( ! defined( 'ABSPATH' ) ) { | |
exit; | |
} | |
/** | |
* Class Post | |
*/ | |
class Post { | |
public $ID; | |
/** | |
* Holds various counters by $context. | |
* | |
* @var Counter[] | |
*/ | |
public $counters = array(); | |
public function __construct( $id ) { | |
$this->ID = $id; | |
} | |
/** | |
* Gets the current count for a given $context. | |
* | |
* @param string $context | |
* @param bool $force | |
* | |
* @return int | |
*/ | |
public function get_count( $context, $force = false ) { | |
return (int) (string) $this->counter( $context, $force ); | |
} | |
/** | |
* Gets a Counter instance for given context | |
* | |
* @param string $context | |
* @param bool $force | |
* | |
* @return Counter|\WP_Error | |
*/ | |
public function counter( $context, $force = false ) { | |
$meta_key = $context . '_count'; | |
if ( ! isset( $this->counters[ $context ] ) || $force ) { | |
$count = $this->get_meta( $meta_key ) ? intval( $this->get_meta( $meta_key ) ) : 0; | |
$this->counters[ $context ] = new Counter( $count, $context, array( $this, "update_count" ) ); | |
} | |
return $this->counters[ $context ]; | |
} | |
/** | |
* Updates count meta. | |
* | |
* @param int|string $count | |
* @param string $which | |
*/ | |
public function update_count( $count, $which ) { | |
$this->update_meta( $which . '_count', $count ); | |
} | |
/** | |
* @param $key | |
* @param bool $single | |
* | |
* @return mixed|false | |
*/ | |
public function get_meta( $key, $single = true ) { | |
return get_post_meta( $this->ID, $key, $single ); | |
} | |
/** | |
* @param string $key | |
* @param mixed $value | |
* | |
* @return bool|int | |
*/ | |
public function update_meta( $key, $value ) { | |
return update_post_meta( $this->ID, $key, $value ); | |
} | |
/** | |
* serialize() checks if your class has a function with the magic name __sleep. | |
* If so, that function is executed prior to any serialization. | |
* It can clean up the object and is supposed to return an array with the names of all variables of that object that should be serialized. | |
* If the method doesn't return anything then NULL is serialized and E_NOTICE is issued. | |
* The intended use of __sleep is to commit pending data or perform similar cleanup tasks. | |
* Also, the function is useful if you have very large objects which do not need to be saved completely. | |
* | |
* @return string[] | |
* @link http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.sleep | |
*/ | |
public function __sleep() { | |
foreach ( $this->counters as $context => $counter ) { | |
$this->counters[ $context ] = (int) (string) $counter; | |
} | |
return array_keys( get_object_vars( $this ) ); | |
} | |
/** | |
* unserialize() checks for the presence of a function with the magic name __wakeup. | |
* If present, this function can reconstruct any resources that the object may have. | |
* The intended use of __wakeup is to reestablish any database connections that may have been lost during | |
* serialization and perform other reinitialization tasks. | |
* | |
* @return void | |
* @link http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.sleep | |
*/ | |
public function __wakeup() { | |
// Reinitialize counters.s | |
foreach ( $this->counters as $context => $count ) { | |
$this->counters[ $context ] = new Counter( $count, $context, array( $this, "update_count" ) ); | |
} | |
} | |
} | |
$post = new Post( 1 ); | |
$share_count = $post->get_count( 'share' ); // Retrieves a new Counter class with the value of get_post_meta( 1, 'share_count', true ); | |
$post->counter( 'share' )->increase(); // Add 1 to the count, which will subsequently update post meta. | |
$post->counter( 'share' )->decrease(); // Subtract 1 from the counter & save. | |
$post->counter( 'share' )->add( 10 ); // Add 10 to the counter & save. | |
$post->counter( 'share' )->subtract( 10 ); // Subtract 10 from the counter & save. | |
// Manage multiple counters quickly & easily, each with its own meta key storage. | |
$like_count = $post->get_count( 'like' ); | |
$conversions = $post->get_count( 'conversion' ); | |
// It even supports serialization. | |
$serialized = serialize( $post ); // a:1:{s:8:"counters";a:3:{s:5:"share";i:0;s:4:"like";i:10;s:10:"conversion";i:3;}} | |
// You could also add quick access functions that wrap counters, such as function get_like_count(). | |
// And you can access counts directly with a little __get() magic, returning them as (int) (string) will do nicely. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment