<![CDATA[Webuml Master Feed]]> http://www.webuml.com/ Tue, 06 Jan 2009 21:33:31 +0000 khelo@webuml.com (Cosmin Dordea) khelo@webuml.com @2007-2008 webuml.com Zend_Feed en http://blogs.law.harvard.edu/tech/rss <![CDATA[Kman , one step closer to a release]]> /blog/index/view/entry/33 Warning: Bad English , proceed with caution

KMan started as a toy for one of my personal projects. What I needed was something that could read rss feeds and notify me when something interesting shows up. In time , I also wanted him to learn from the feeds. For example , kman reads feeds and after a while I ask him about mvc, and he sums up some facts. The bot should also direct me to ..]]> Warning: Bad English , proceed with caution

KMan started as a toy for one of my personal projects. What I needed was something that could read rss feeds and notify me when something interesting shows up. In time , I also wanted him to learn from the feeds. For example , kman reads feeds and after a while I ask him about mvc, and he sums up some facts. The bot should also direct me to various sources of information based on some keywords(mvc for examle) . The implementation evolved, and now you can implement various applications based on it.

Potential - Sample Applications

This bot is not just about fun , it's intended to be useful. For example , suppose you have an internal jabber server. You can customize this bot to the extent that your team can log the progress without the web browser or get a list of available tasks , etc. This can be easly be implemented using commands(which are described later).

Another example , if your computer is behind a firewall ,you can control it via a bot connected to a gmail account(of course ,you have to be careful so that it will listen only to you). You can also index your documents , movies , etc and query the bot for them (using Lucene or something like that)

And , as I stated allready ,you can create an application that monitors some rss feeds and announces you when new feeds are available. Before reading them , you will be able to ask the bot few things about the posts and decide if the post is worth reading. This feature is not complete yet, but you can get a glimpse of it as described later.

How can the bot be used like this?(Key Features)


Megahal

First of all ( in time it will be the least important) it will be provide a 100% megahal implementation. For the moment , it provides only a partial implementation.

Megahal implementations are based on Markov chains (math stuff),which enable you to generate content based on previously parsed content. For example , if megahal encountered the word A followed by the word B , and at some point , the word B followed by the word C , it will be able to generate A B C , or A B, or B C. Being based on math , rather than on rules , it's language independent.

Here is an example after feeding the bot with two wiki pages related to aliens,predators and leonidas:


A trio of Predators seen aboard their spacecraft  is available  under the 
assumption that Leonidas gave the Predator's face, as shown in Predator.

Here is what you can get by feeding the bot with an irc log and some dune quotes and then providing a keyword that will be the base for the generated responses:


you>feed http://en.wikiquote.org/wiki/Dune
kman>Mmmmm , that was good
you>feed http://www.irclog.org/freenode/php/2006-05-10/page1.html
kman>Mmmmm , that was good
you>CMS
kman>There is no substitute  on CMS' s 'try to remember, 
there is no substitute for intelligence.
you>CMS
kman>Seeing this and telling of it, he made the audacious leap  based CMS  
for editing and maintaining around 50 pages, with support for password 
protected areas, printer friendly versions 
of all was the price we paid was the basic 
trust that he made the audacious leap of decision.

A final example , here is what I can get after feeding the bot with my homepage:


Php Megahal 
you>feed http://www.webuml.com
kman>Mmmmm , that was good
you>webuml
kman>You can find here my blog ,some  experiments (various tests that i do for
 personal use) and most of the intersting stuff i found on the net and became
 part of my never ending training, which covers: 
PHP5 Zend Framework Adobe Flex More Links     2007 webuml .
you>blog
kman>Until then , this site will act as my  my blog , some  experiments (various
 tests that i do for personal use) and most of the intersting stuff i found on 
the net and became part of my never ending training, which covers: PHP5 Zend
 Framework Php Frameworks(in general) OOP/OOD Until time will allow me to focus
 on webuml, this site will act as my personal site.

In the future , I will have a Term Extractor that will tie your sentence with the next response, right now I am using random stuff : "What can you tell me about CMS?" can generate sentences based on any word from the question. The Term Extractor will be based on Markov Chains as well , so it can be used in any language. This will be a key feature for previewing your rss feeds via your bot.

Flexibility

Megahal is not everything about this bot , there will be several other 'brains'(infobots are scheduled) available or combinations. You will be able to use any of them , under any supported protocol. Here is how you can setup a cli bot:


$kman  = new Kman_Communicator_Cli();
$brain = new Kman_Megahal_Brain();
$kman->setBrain($brain);
$command = new Kman_Communicator_Command_Demo();
$kman->addCommand($command);

We will talk about commands later , for now here is how you would setup a gmail bot:

$kman = new Kman_Communicator_Xmpp('talk.google.com', 5222, 'user', 
'password', 'xmpphp', 'gmail.com');
$command = new Kman_Communicator_Command_Demo();
$kman->addCommand($command);
$command = new Kman_Communicator_Command_Say();
$kman->addCommand($command);
$megahal = new Kman_Megahal_Brain();
$kman->setBrain($megahal);
$kman->connect();

As you can figure , it doesn't matter what kind of protocol or brain you are using, you can achieve several results by using the same code base. You can build several different bots while sharing some of the code.

Extensibility

You can customize or add new features to the bot without having to know about how all is made. You have seen in the previous snippets something about a command, here is what say command does:


Php Megahal 
you>say moo
kman>moo

and here is how it is implemented:

class Kman_Communicator_Command_Say implements SplObserver 
{
    public function update(SplSubject $subject)
    {
        $message  = trim($subject->getMessage());
        if(!strpos($message," ")) {
            return;
        }
        list($command,$what) = explode(' ',$message);
        if($command == 'say')
            $subject->setResponse($what);        
    }
}

You will receive something that implements the SPLSubject interface. As a side note , this tehnique is a design pattern , called the Observer Pattern, and you can read about it here. The full interface will be available in the future , but right now , I don't want extensions to be strongly coupled to my code(even my own).

If you haven't figured it already, whenever Kman receives a message , your command will be called and you can do whatever you want there , based on the received message or other factors.

So far, you have seen that you can use cli and xmpp. You can add any other protocols you may desire, and the bot will work the same . To do this , you have to extend an abstract class, called Kman_Communicator_Abstract , or you can implement something from scratch (You can use Kman_Communicator_Interface as a guideline or better , implement it.) Here is how the cli engine is implemented:


class Kman_Communicator_Cli extends Kman_Communicator_Abstract 
{
    
    public function connect()
    {
        $handler = fopen("php://stdin","r");
        $message = "Hello";
        echo "Php Megahal ";
        $bye     = null;
        while ($message != $bye) {
            echo "you>";
            $message  = fgets($handler);
                        
            $response = $this->getResponse($message);
            
            if($response) {
                $this->send($response);
            } else {
                $this->send('moo moo baa baa , me stupid');
            }
            
        }
    }
    
    protected function send($message)
    {
        echo 'kman>',$message ;
    }
}


Not so difficult , is it? In the future(next weekend perhaps) , I will also hook the irc protocol.

How can you get the code


svn checkout http://kman.googlecode.com/svn/trunk/ kman-read-only

There is no documentation at the moment, only some examples found in the scripts directory. The API is subject to changes(until the first release) , but not major changes. The project uses some code from Zend_Framework, New Bsd License and xmpphp, which is under GNU License.

That's it for now, I will come back with 0.1 .

]]> Tue, 06 Jan 2009 21:33:31 +0000 comments page of the feed entry
<![CDATA[two words about what php lacks]]> /blog/index/view/entry/11 There are many occasions when I would want more features from php , I will list only two , that are related to my previous post , the one about Zend_Feed.

Late static bindings

One of the things I wanted for a time now , is the so called late static binding. I will let all the theoretical details and what is it good about to the many posts that will follow about thi..]]> There are many occasions when I would want more features from php , I will list only two , that are related to my previous post , the one about Zend_Feed.

Late static bindings

One of the things I wanted for a time now , is the so called late static binding. I will let all the theoretical details and what is it good about to the many posts that will follow about this subject, I will just post an example of something that you can't do properly in php5. In my previous posts I had at some point a uml diagram , with two factories there. What I really wanted is to also provide something like:


abstract class Wu_Feed_Factory
{

   private static $instance = null;

   protected function __construct()
   {
   }

   public static function factory()
   {
       $instance = $this->getInstance();
       $feed = $instance->create();
       $feed->add($this->buildSource());
   }

  abstract protected function buildSource();

  //can be protected or public same thing
  private function getInstance()
  {
     if($instance == null) {
         //will always refer to Wu_Feed_Factory
         //and this is the problem
         $instance = new __CLASS__;
     }     
  }

  private function create()
  {
      $feed = new Wu_Feed();
      //init code here or whatever
      return $feed;
  }

}

class CommentsFeed extends Wu_Feed_Factory
{
    protected function getSource()
    {
        //.....
    }
}

//later in the code
//woun't work , will always use the base class
//as an instance
$feed = CommentsFeed::factory();

If this code is necessary , it doesn't matter , I just wanted to provide an example. Here is a shorter one:



//extract from the official php documentation
class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        self::who();      
    }  
}  

class B extends A {      
    public static function who() {
         echo __CLASS__;
    }  
}   

B::test();//outputs A 


Luckly , this feature will be released with php 5.3. and I will be able to play more with the static methods and attributes, cool ... but I needed it way sooner.

Method overloading

I saw many people arguing about this, but what php offers it is not method overloading, it's more like a method not found handler , which is very handy indeed .. but I am tired to do crap like this:



public function loadFromArray($array)
{
}


public function loadFromFile($path)
{
}

public function loadFromObject($object)
{
}

or faking it:

public function load($resource)
{
   if(is_array($resource)) {
      return $this->_loadFromArray($resource);
   }

   if(is_string($resource)) {
     //etc
   }
   //etc
}

From my point of view , my interface would be much cleaner if there would be something like:

public function load(string $string);
public function load(array $values);

I believe this is much cleaner and I also believe that a class coded this way can be safely extended when new resources are added. You will not have to deal with countless methods or all kind of crap that emulates method overloading.

emphpower

Even if you may not agree with my points , chances are that you probably wanted something from php at some point and you were not the only one . What can you do when your voice in the php community is next to null(it's not impossible but it is a long journey)? It's difficult to make people listen to you if you are not a prolific blogger or you are not part of some cool open source projects. There is an alternative now , and it is called emphpower. It may not be the perfect solution , but it is the least you can do.

K.

]]> Tue, 06 Jan 2009 21:33:31 +0000 comments page of the feed entry
<![CDATA[Creating Custom Feeds with Zend_Feed - part 1]]> /blog/index/view/entry/10 I had some time this weekend and I implemented the 'latest stuff'(news) feature. Now I can create feeds based on my posts or any other source I want. I can even combine external feeds,atom or rss ,to create a master feed and all this thanks to Zend_Feed

Here is an example on how you can combine three feeds ..]]> I had some time this weekend and I implemented the 'latest stuff'(news) feature. Now I can create feeds based on my posts or any other source I want. I can even combine external feeds,atom or rss ,to create a master feed and all this thanks to Zend_Feed

Here is an example on how you can combine three feeds , one rss , one atom and a local source to create a master feed:


$feed          = new Wu_Feed();
$remote_source = new Wu_Feed_Source_Remote('http://remotefeed.com/atom');
$feed->add($remote_source);
$remote_source = new Wu_Feed_Source_Remote('http://remotefeed.com/rss');
$feed->add($remote_source);

//of course you can have a builder
//object or a factory to cotain
//the local source building part
$local_source = new Wu_Feed_Source(); 
$entry = new Wu_Feed_Source_Entry();  
$entry->title = 'New Title';
$entry->content 'awesome content';
$local_source->add($entry);

$feed->add($local_source);
echo $feed->asRss();//outputs rss feed
//or
$feed->asAtom();//outputs atom.
//
$zend_feed = $feed->asZendFeed();//returns Zend_Feed object

I think asRss() and as asAtom() are clear, but what about the latest, asZendFeed()? Why would I need a Zend_Feed object, doesn't Wu_Feed inherit Zend_Feed ? No , it doesn't, but I am using it within Wu_Feed to do my work. I will explain more in the 'how it works' section.

If you noticed , my left navigation has a section 'Latest stuff'. Until now , it displayed my recent bookmarks , stored on a blogspot account. The code that did that was:


  $feed     = Zend_Feed::import('http://dordea.blogspot.com/feeds/posts/default');
        $results = array();
        foreach ($feed as $entry) {
            $result          = array();
            $result['title'] = $entry->title();
            $result['link']  = $entry->link('alternate');
            $results[]       = $result;
            
        }

        $this->view->results = $results;
        

Basically , to fill my left nav , I was using an external feed , because I was to lazy to make my own. The reason why asZendFeed() method exists is:

  • to have my original code working with no major modifications
  • to be sure my addons will work with any other classes that use Zend_Feed , from Zend Framework or from any other source
If you are thinking about performance , Zend_Cache does a wonderful job and allows me to ignore this part(at the moment) .
The code that fills my left nav is now:

$feed     = Wu_Feed_Factory::getLocal()->asZendFeed();
        $results = array();
        foreach ($feed as $entry) {
            $result          = array();
            $result['title'] = $entry->title();
            $result['link']  = $entry->link('alternate');
            $results[]       = $result;
            
        }

        $this->view->results = $results;

At some point , I want to alternate the 'Latest stuff' source(so that i could combine and filter the news using external or internal feeds).It makes sense (at least for me) to treat my news as a feed. If this 'plan' will fail in the future , at least now I have rss and atom feeds. Another important reason for going trough this 'effort', is that I will also use this code as a base for my new project.

How it works

Zend_Feed, by default , allows you to create your own feed, not just to import one. You can do that by using a big array (and by big i mean really big) or implementing the Zend_Builder_Interface(see the above link for details). Basically, you would do one of:



// importing a feed from a custom builder source
$atomFeedFromArray = Zend_Feed::importBuilder(new Zend_Feed_Builder($array));

// the following line is equivalent to the above; 
//by default a Zend_Feed_Atom instance is returned
$atomFeedFromArray = Zend_Feed::importArray(new Zend_Feed_Builder($array), 'atom');

// importing a rss feed from a custom builder array
$rssFeedFromArray = Zend_Feed::importArray(new Zend_Feed_Builder($array), 'rss');

// Note: This sample of code is extracted from 
// the Zend Official documentation
// http://framework.zend.com/manual/en/zend.feed.importing.html

The first line of code has the same effect as the second and it's even the same array, but do not be confused . Zend_Feed_Builder is just a sample implementation. The ideea is that you implement Zend_Feed_Builder_Interface and trough that interface , the feed will query you for a Zend_Feed_Header(via getHeader()) and a set of Zend_Feed_Entry(via getEntries()) objects.

Sounds nice , but for my first version , I preferred a set of objects that build the array mentioned before Zend_Feed_Builder kicked in. The reason? I find it more comfortable and I will not be tied to a data source. I can implement(and I will) a builder later, for now here is how I am using the classes I created. Generic Example:


title      = 'Example for my post';
$entry              = new Wu_Feed_Source_Entry();
$entry->title       = 'Hello world from a feed';
$entry->description =  'hello ..';
$entry->content     = 'Elaborate words about hello
 world';
$source->add($entry);
$feed = new Wu_Feed();
$feed->add($source);
echo $feed->asAtom();//outputs atom feed xml

To reduce the code I am writing, I am using some factory objects to create my feed source. One for the Wu_Feed objects, and one to create the source. Here is how the uml diagram looks:

feeds uml diagram

Wherever I need my feed, I am using Wu_Feed_Factory . This will protect me from any changes that I will make regarding the feed building process. Also , important to note , is that I am not inheriting Zend_Feed. Why? To protect me from myself and from any future changes that (perhaps) will affect Zend_Feed. I am using my classes to build the array needed by Zend_Feed to create the actual feed. Zend_Feed is used only when I actually need the output(or a Zend_Feed). There are other benefits to this approach , the most important for me: time. Again, I obtained a quick prototype of what I want to achieve in short time , but it's not a dirty solution. I can change anything regarding the building process , and my code that uses Wu_Feed will stay the same , as long as I obtain the feed object trough the same factory and my main methods add,asAtom,asRss and asZendFeed have the same effect.

Now , again , I am sure there are way better implementations and uses of Zend_Feed. But as something that I am doing in my free time , this solution works for me and took me around 1h to implement it. My point , again, is that you can quickly prototype something with a framework like ZF behind, and still , protect your present and future code from anything you don't master yet once you decide on how you want to use your new feature , which is the most important(and difficult) part most times(aka design).

What's next

After I will provide a standard way for you to build feed sources wihthout having to modify and understand the existing code (non existent php5 late static binding support delayed me) , I'll provide a link to the code presented here. Before that , I will use ZF to implement 'nice urls'. So instead of /blog/index/view/entry/123 to have /thinking_about_auth.html.

P.S.: You are free to call me a retard if this post was a waste of your time and had problems reading my non-sense.

K.]]> Tue, 06 Jan 2009 21:33:31 +0000 comments page of the feed entry
<![CDATA[Writing a quick auth plugin with ZF(Zend_Controller_Plugin)]]> /blog/index/view/entry/9 One good thing about a framework is that if you trust the people who it and have a basic idea (with some tools out there you don't even have to) on what's behind you can easily add new functionality or temporary hacks to your site without having to fully understand what's behind. This is really one of the things I love regarding well written OOP code:possibilities. I can quickly prototype an..]]> One good thing about a framework is that if you trust the people who it and have a basic idea (with some tools out there you don't even have to) on what's behind you can easily add new functionality or temporary hacks to your site without having to fully understand what's behind. This is really one of the things I love regarding well written OOP code:possibilities. I can quickly prototype and with some thinking ahead, I will make sure my further development will not be crippled by some early hacks. .

As I stated in my first post, I am developing webuml from scratch and I will post most of my work here. Why don't I use an already available solution? Because it's good for my brain and soul and I will get used to do some extra work in my spare time (so I can finally start working on webuml - the tool). Besides, I know best what I need and it's a good training exercise ,considering that most of my work is related to the backend part.

Problem

Okay ,let's talk about a hack I did that took me around 10-15 minutes , less than this post. Yesterday , when I started to upload my webuml code and wrote my first post , I realized I didn't setup any kind of authentication for my admin area :D. Because the whole user thing is not planned yet(to lazy actually), I quickly wrote a plugin to handle the authentication for me.
Here is the relevant code:


class Wu_Plugins_Auth
{
public  function routeShutdown(Zend_Controller_Request_Abstract $request)
    {
        $module = $request->getModuleName();

        if($module != 'admin') {
            return;    
        }
        $auth_data =  $this->_request->getParam('user');
        if($auth_data) {
            $this->doAuth($auth_data);
        }
        
        $auth_namespace = new Zend_Session_Namespace('auth');
        if (!isset($auth_namespace->logged) ||
     !($auth_namespace->logged == 'yes')) {
            $request->setModuleName('default');
            $request->setControllerName('index');
            $request->setActionName('login');
        }
    }

private function doAuth($authData)
{
//doesn't matter right now
}

}

Now what I like about this is it's a quick and easy to write hack and , what I like the most , the rest of the application is not aware of the authentication mechanism. Besides writing the plugin , there were two other things I had to do. First was to create a login action (just to display my html form) in my main index controller. To do that I had to add this code in it:


public function loginAction()
{
//I will just delete this or
//move it when I will decide on a permanent
//solution
}

and created a simple html form which is automatically rendered for me by the caring Zend Framework behind my site. I am also using Zend_Layout, so adding new html content(or templates) to my site is really a very simple thing when you don't require fancy stuff.(I will post examples and stuff at some time regarding Zend_Layout).

The next big thing I did was to tell my front controller to actually use the plugin, which is again a lot of code:


//this line here is in index.php
$controller->registerPlugin(new Wu_Plugin_Auth());

With those things in place , you can disable/enable auth by just commenting/uncommenting that line.

How does it work?

At the heart of most of Zend Framework powered websites lies Zend MVC , which has it's own heart , the Zend Controller. If you never ever played with the Zend Framework , I recommend you the Quick Start first. The Zend_Controller dispatch process (in short and not complete) goes like this:

  • The url is analyzed and based on some default or custom rules(routes) , the framework will know what module , controller and action to execute. The result is stored in the Request object.
  • Based on the information found in the request object, the appropriate action is executed by the dispatcher object

Now ,ZF provides hooks before and after each phase. You can access these hooks by extending the Zend_Controller_Plugin_Abstract abstract class and implementing the method responsible for the hook your interested in. In my case , it's route shutdown(routeShutdown) , which takes place after the routing process is done. Why do I do that? Because I want to know if the dispatcher will go in the admin module, and if yes, re-route to the login action in case the super user is not logged. Note that the auth process also takes place here, because I want all the logic to be contained in one place so I will not have problems later.

I truly agree with any one who says there are plenty of other ways to properly do this auth thing, but imagine that it took me only 10-15 minutes to write this and it will do it's job until I will decide on a permanent solution. I have gained valuable time by using this simple solution and my point was to demonstrate how easy you can prototype something without affecting the rest of the application code.

Plugins , in general , are cool things. You can slightly alter the functionality on demand. Instead of modifying the bootstrap , you can have another class to load your plugins in the front controller. The plugin names can be stored in a config file, or db , or whatever. You will be able to add functionality to your site without modifying your current code , which is cool. What can they contain? Anything: debugging tools , redirect, custom personalized navs, fancy layout switching rules. For a large user base for example , instead of checking a lot of conditions or performing a lot of queries or whatever , you load the appropriate plugins. Anyways , possibilities.

Next time I'll implement the 'latest stuff thing' ,which is "my post titles will be displayed in the front page". I will try to make it so that I can combine feeds or other sources(my del.icio.us links for example) into one single 'source' which should be used to generate a master rss feed(or how should I call it).


Laterus,
K.]]>
Tue, 06 Jan 2009 21:33:31 +0000 comments page of the feed entry
<![CDATA[$this->sayHello($world);]]> /blog/index/view/entry/8 I bought this domain a while ago for yet another cool idea that I had , but didn't had time to implement it yet and I doubt I will have soon (and not to forget , I am also lazy in my free time).
I tried at some point to enter in the PHP world via a blog, article or contributing to an open source project(Zend Framework for example , which I love) but I w..]]>
I bought this domain a while ago for yet another cool idea that I had , but didn't had time to implement it yet and I doubt I will have soon (and not to forget , I am also lazy in my free time).
I tried at some point to enter in the PHP world via a blog, article or contributing to an open source project(Zend Framework for example , which I love) but I wasn't sure how to do it so that I could sleep well at night , because most of my jobs assumed a pretty strict NDA, launching an idea that was previously developed by me in a company or looks similar to what somebody did can be ..hmm .. nasty. All you open source guys , I greet you , your work(code , presentations , books and even argues) provided me with invaluable knowledge , I am sorry I can not give back as much as I can , but this is life. However, perhaps this is a good thing , because my skills are not complete yet. I have serious flaws in many categories but I am doing my best to cover them.
I pondered for a long time what I could do to gain a insignificant place on the web. At some point I tried to write an article for php|architect, but due to NDA problems(actually I got scared) , I let them down(sorry, really sorry) and never completed it. Now , after some time , I am trying to start webuml and also kman, as a tool for another future web project of mine, which I hope it will be launched soon.
I hope I will not bla bla often(see above and bellow text), because I will try to be more technical in time.. I am developing webuml.com from scratch and I will be detailing the process as I do it. Right now , I only have a simple structure based on Zend Framework's MVC model(I will detail at some point why I like Zend Framework) , a simple table to keep the posts and some other simple stuff. I will add a lot more features , custom made for this site. The first to be done would be the blogging platform. I will not just tell you how but why.
Hopefully this is is not my last post and I will not make a fool of myself.
K. ]]>
Tue, 06 Jan 2009 21:33:31 +0000 comments page of the feed entry