Atilla Ördög

Personal site of Atilla Ördög AKA Gadratil

Tag: PHP

PHP Infinity tree

inline

I created a new library to handle infinite depth trees. I came up with the idea and the necessity because I always struggled to find a good library that can be simply loaded and used for infinite depth category trees, whole sub-node movements, easy node movements and such.

Also my main concern was how the tree gets stored in the database. I came up with a new idea based on MPTT, that stores the data in linear style, not using up much extra space and does not require recursive functionality in the storage. The tree itself is built up by a recursive function that builds the tree using N iterations, no overhead.

screenshot

So, the whole thing is quick, runs smoothly and deals with only the tree, nothing else.

You would ask: how can it be implemented?

This library simply adds a PHP interface to infinite depth trees. That’s it. But since it uses namespaces and replaceable adapters, it can be easily implemented anywhere.

So, let’s see the library:

A fully working example and the full documentation can be found at:

PHP Infinity Tree example and documentation

You can purchase the library here:

PHP Infinity Tree on Gadratil Programming

If you have any questions, just ask. Also, if you need implementation, I would gladly help you.

Advertisement

PHP Image Handler

I wrote about the image handling library I made. The small code snippet I wrote was poor and hard to understand.

I optimized the code and created example and documentation for my Image Handler PHP library.

Now it can be found on Gadratil Programming in the shop section.

Make your life easier using this library by adding it to any custom framework or CMS.

PHP Image Handler

 

Server Messaging made easy

I will talk in this article about a library I made for making easy server side messaging.

It is called ServerMessage and is a library for creating and sending messages on server. By default it saves the messages in DB, but the storage can be changed by implementing the storage interface and passing the new storage when creating the instance.

Also it has a very basic validation that can also be changed in the way described above.

It is a very flexible library, it can be used for a lot of things and in a lot of ways.
A functionality I am proud of is the filtering, currently it has two filter options added, one filters out emails and the other filters out urls. Other filters can be added, too, by implementing the filter interface and passing the filter when filtering.

A very basic example of usage:

include('autoload.php');

// Instantiate the class using explicit values
$message = new ServerMessage(
array(
'db' => array(
'server' => 'localhost',
'user' => 'root',
'pass' => '',
'database' => 'test',
'table_name' => 'messages'
)
)
);

// Check if storage exists and create it if does not
if ( !$message->storage_exists() )
{
$message->install_storage();
}

// Create message
$message->set_subject('Testing message abc@bcd.com');
$message->set_body('Body of the message, also containing filterable things like http://www.filterurl.dev or abcd@efgh.dev');
$message->set_sender(1, 'user');
$message->set_reciever(1, 'support');
$message->set_meta(array('meta_key' => 'meta_value'));
$message->send();

// Now the message is also set in the inner container, thus we can change one thing and send the message again.
$message->set_reciever(2, 'support');
$message->send();

// You can also update the message
$message->set_subject('Changed');
$message->update();

// To reset inner message, you can call
$message->reset_inner_message();

// Filtering messages is easy like
$message->filter_message();

It can be used in a lot of ways. Here is the full list of functions with docx descriptions for reference:

/**
* Constructor.
* @param array $config Can overwrite default config upon creation
* If no storage class is provided, the config default will be used
* @param ServerMessageInterfacesStorage $storage
* @param ServerMessageInterfacesValidation $validation The validation class that validates the message, can be set externally
*/
public function __construct(Array $config = array(), StorageInterface $storage = null, ValidationInterface $validation = null)

public function set_subject($subject = '')

public function set_body($body = '')

public function set_sender($sender_id = 0, $sender_type = '')

public function set_reciever($reciever_id = 0, $reciever_type = '')

public function set_meta($meta)

/**
* Set the status of one or more messages
* @param array|int $id
* @param int $status Must be one from the predefined statuses
* @return boolean
*/
public function change_status($id, $status)

/**
* Set one or more messages to read or unread
* @param array|int $id
* @param boolean $read True or false
* @return boolean
*/
public function set_read($id, $read)

/**
* After the parts of the message have been set, saves to storage
* If validation is set to true in config, validates before sending
* @return boolean
*/
public function send()

/**
* Updates the loaded message in the storage
* It will validate the message if set in config
* @return boolean
*/
public function update()

/**
* If sending was not successful, we get the validation errors
* @return array
*/
public function get_validation_errors()

/**
* Gets the inbox of a given object
* @param int $obj_id The id of the reciever
* @param string $obj_type The type of the reciever
* @param int $status Optional, taken in consideration if not null
* @param int $limit
* @param int $offset
* @return array Returns an array with message objects
*/
public function get_inbox($obj_id, $obj_type, $status = null, $limit = null, $offset = null)

/**
* Gets the number of messages in inbox
* @param int $obj_id The id of the reciever
* @param string $obj_type The type of the reciever
* @param int $status (Optional) Status filter
* @param int $read (Optional) Read filter
* @return int
*/
public function get_total_inbox($obj_id, $obj_type, $status = null, $read = null)

/**
* Gets the outbox of a given object
* @param int $obj_id The id of the sender
* @param string $obj_type The type of the sender
* @param int $status Optional, taken in consideration if not null
* @param int $limit
* @param int $offset
* @return array Returns an array with message objects
*/
public function get_outbox($obj_id, $obj_type, $status = null, $limit = null, $offset = null)

/**
* Gets the number of unapproved messages
* @param int $obj_id The id of the reciever
* @param string $obj_type The type of the reciever
* @param int $status (Optional) Status filter
* @return int
*/
public function get_total_outbox($obj_id, $obj_type, $status = null)

/**
* Get all the messages, pagination dependent
* @param int $limit
* @param int $offset
* @return array
*/
public function get_all($limit = null, $offset = null)

/**
* Get the total number of messages
*/
public function get_total_messages()

/**
* Get a single message by ID or the current message set
* @param int $message_id If null, returns current message
* @return ServerMessageEntityMessage
*/
public function get_single($message_id = null)

/**
* Deletes one or more messages
* @param array | int $message_id
* @return boolean
*/
public function delete_message($message_id)

/**
* Checks if storage exists and can be used
* @return boolean
*/
public function storage_exists()

/**
* Creates storage if that does not exist
*/
public function install_storage()

/**
* Clear out the storage created for messages
*/
public function remove_storage()

/**
* Filters the given message
* @param ServerMessageEntityMessage $message Optional, if not set, the inner message will be used
* @param array $filters Optional, can be used to add filters (Ex. array('facebook' => new FacebookFilter()))
* The filters need to extend the filter interface
* @param boolean $subject_only Filter only the subject
* @param boolean $delete_found Remove the found matches from the message
* @param boolean $save If true, saves the message back to storage (used when deleting threats)
* @return array Returns an associative array with the filtered message and the found matches
*/
public function filter_message(MessageEntity $message = null, Array $filters = array(), $subject_only = false, $delete_found = false, $save = false)

/**
* Return the inner statuses set in config
*/
public function get_statuses()

/**
* We need to reset our message entity sometimes, so we do that with this function
*/
public function reset_inner_message()

The source code can be found here:

https://github.com/atillaordog/ServerMessage

ImageHandler, a small and useful tool

Usually every CMS and Framework has its own image handling class. The problem is between, however, because in a CMS image handling is part of a media library that is big and complex.

In a Framework image handling is not done at all, it just has some classes for helping the developer.

This gap is what I tried to fill by creating a small tool for handling images.

This tool is very lightweight, easy to use and covers a large area in image handling.

It is created in a way that a developer can easily change the storage and validation classes if needed. Currently data is saved into DB using Mysqli and validation checks basic aspects.

Configuration can be passed using the Config class and the config file in the base folder, but config params can be passed upon initialization, too.

The image handling is done by Kohana`s Image library, surely it is a bit modified to fit my needs. This tool uses GD or Imagick library, so you will have to enable that if you want to handle images.

What you will need to run this code: PHP 5+, mysqli, GD or Imagick

Here is a full sample of the usage of this library

include_once('ImageHandler/autoload.php');

// Initialize the class, it loads config from the config file, but configs can be overwritten from here
$imageHandler = new ImageHandler(
array(
'sizes' => array(
'normal' => array('width' => 50, 'height' => 50)
),
'db' => array(
'server' => 'localhost',
'user' => 'root',
'pass' => '',
'database' => 'test',
'table_name' => 'images'
),
'base_path' => dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test_images'
)
);

// Check if storage exists and create it if does not
if ( !$imageHandler->storage_exists() )
{
$imageHandler->install_storage();
}

// Check if we have to delete
if ( array_key_exists('delete_image', $_GET) )
{
$imageHandler->delete_image_by(array('object_id' => 1, 'object_type' => 'test'));
}

// Handle POST
if ( $_POST )
{
if ( array_key_exists('image', $_FILES) )
{
// Validate and save image
if ( $imageHandler->validate_image($_FILES['image']) )
{
$imageHandler->save_image($_FILES['image'], 1, 'test', 'test_images/1');
}
else
{
var_dump($imageHandler->get_errors());
}
}
}

echo 'Current image:';

$images = $imageHandler->get_image_by(array('object_id' => 1, 'object_type' => 'test'));

var_dump($images);

You can find this library here: https://github.com/atillaordog/ImageHandler

Easy Pagination helper

One of the first things I wrote when I started working in PHP was a nice little Pagination helper class.

It is very easy to use and made my work easier many times.

So here it is a code sample of how to use it:

// First we have to get the total elements

// Create the limit, offset and other useful data first
$pag = Pagination::paginate($total_nr, $current_page, 20);

// Here we get our data using limit, offset

// Build the pagination
$pagination = new Pagination(array(
'total' => $total_nr, // The nmber of all elements
'items_per_page' => $pag['pagination'], // How many items will there be on the page
'base_url' => $url,  // The base url used, this can contain $_GET elements too, they will not be overwritten
'current_page' => $pag['current'], // Current page we are on
'links_to_show' => 3, // How many links to show between the 3 dots
'page_name' => 'sm_page', // Name of the $_GET parameter to use
'first_string' => '<<', // String that is used for the FIRST link
'prev_string' => '<', // string used for the PREVIOUS link
'dots_string' => '...', // String used for the dots between numbers
'next_string' => '>', // String used for the NEXT link
'last_string' => '>>' // String used for the LAST link
));

// Generate the array of pagination links
$pagination_links = $pagination->render();

You can also set the mentioned variables after initialization like:

$pagination->base_url = '';

Note that you have to set all variables before calling render()

 

It can be found here:

https://github.com/atillaordog/Pagination

Validation Wall

I re-imagined data validation in PHP. Why did I do this? I found that current validation techniques are too strict and cannot be used alone.

So, I thought the following: validation is like a filter. A wall that has different doors, each door specific to a set of data. Data comes and in order to reach its destination, it has to go over the door. Now the door has rule-sets, these are the rules specific to a part from the data.

These rule sets are built from rules, that are the basic rules found in any validation system.

A wall can be built easily by simply grouping the rules to fit our needs.

Here is an example:

$title_ruleset = new MainRuleset('title', array( new NotEmpty() ));
$description_ruleset = new MainRuleset('description', array( new NotEmpty() ));
$categories_ruleset = new MainRuleset('categories', array( new NotEmpty() ));

$door = new Door(array($title_ruleset, $description_ruleset, $categories_ruleset));

$vw = new ValidationWall($door);

$post_passes = $vw->pass($post);

In this example we use the NotEmpty rule to check the title, the description and the category.

 

To use ValidationWall, you have to include the autoload file like:

include_once route/to/ValidationWall/folder/autoload.php';

Also you have to use the namespaces like:

use ValidationWallDoorMainDoor as Door;
use ValidationWallRuleSetMainRuleset as MainRuleset;
use ValidationWallRuleNotEmpty as NotEmpty;
use ValidationWallRuleNumeric as RuleNumeric;

After you initialized ValidationWall, you can start building your wall to fit your needs.

Main benefits:

  • It is totally stand-alone, usable anywhere in any script
  • Logically more understandable than general validation
  • Rules are custom, meaning you can build any rule you want, you just have to implement the interface or extends the abstract class
  • Build validation like you are playing Lego

You can find this little code here:

https://github.com/atillaordog/ValidationWall