A tool to help searching tags
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


#Majax TagParser

This project aims to help make tags much more useful for search and filtering.

Based on the initial lexer/parser concept from:


What does it do?

To make a long story extremely short, it lets you use natural equation expression to search your tags.


a + b // addition: return all from tags A and B

a - b // subtraction: return all from tag A not in B

a|b // limit: returns only tags from A also in B

a^b // exclude: returns all from tag A not in B, chainable with limit

a^b|c // returns all from A not in B which are also in C

(a + b) - (c + d) // supports parenthesis for your sanity

Interesting to note:

Tags with limit/exclude and groupings (expressions in parenthesis) are optimized and will only be resolved once per unique expression.


Import into your project and either include in your autoloader or use the autoload.php file to autoload it.

Then there are two steps to fully resolve a given string.


$string = 'a + b';
$lexer = new Majax\TagParser\TagLexer($string)
$parser = new Majax\TagParser\TagParser($lexer);

$parsed_structure = $parser->process();


Building Your Repository

To resolve, you will need to pass a repository to the Resolver. The signature needed to be implemented is:

  * @abstract
  * @param $tag String
  * @return string[]
 public function getIdsForTag($tag);

In Symfony 1.4.x, a repository could look like:

 * PluginTagTable
 * This class has been auto-generated by the Doctrine ORM Framework
class PluginTagTable extends Doctrine_Table implements \Majax\TagParser\TagRepositoryInterface
     * @param $tag String
     * @return string[]
    public function getIdsForTag($tag)
        $sql = 'SELECT tt.thing_id FROM tags t, thing_tags tt WHERE rt.tag_id = t.id AND t.name = ?';
        $results = $this->getConnection()->execute($sql, array($tag));
        $res = $results->fetchAll(Doctrine::FETCH_ASSOC);
        $results = array();
        foreach($res as $row)
            $results[] = $row['thing_id'];

        return $results;


Creating the resolver

Now you just have to pass this into the resolver like so (we will use Symfony 1.4.x as an example again):

$resolver = new \Majax\TagParser\Resolver(Doctrine::getTable('Tag'));

$thing_ids = $resolver->process($parsed_structure);

Let's show it as a cohesive example, just for good measure...

$string = 'a + b';

$parser = new Majax\TagParser\TagParser();

$repository = Doctrine::getTable('Tag'); // platform/framework/implementation specific

$lexer = new Majax\TagParser\TagLexer($string); // alternately can call ->setInput() instead of constructor

$parsed_structure = $parser->process($lexer);

$resolver = new \Majax\TagParser\Resolver($repository);

$thing_ids = $resolver->process($parsed_structure);


Improve tests