Agile Toolkit is branched for refactoring

Wednesday, April 28th, 2010|Core changes|by Romans

I have been working on a refactoring in a separate branch. Right now it looks stable, so I’m putting more details in here:

https://agiletech.ie/svn/amodules3/branches/romans/pathfinder/

(you can try new branch by using svn switch)

What’s new

PathFinder

The largest change is introduction of PathFinder. I have already mentioned it. The purpose of the class is to unify not only loading of different things, but it links together the concepts of URL and Paths. For example, let’s say you are looking for myfile.js. This file could be located in several locations, templates/js, amodules3/templates/js etc. PathFinder collects information about all available locations and what type of files are there. It also tries to identify the base URL of each location, so if you want to provide http link to myfile.js, you can do so.

The interface with the new class looks very simple. You do not need to do anything – it work out of the box. It will automatically load with any API. It will automatically include your base location and amodules3 library. If you are using more locations (addons, other modules), you will have to add them:

$this->api->addLocation(‘addons’,'php’);

This instructs that the new directory which is relative to base path will contain additional php classes. You can also attach locations containing multiple resource types:

$this->api->addLocatoin(‘modules/helpsystem’,array(‘js’=>’js’,'php’=>array(‘lib’,'experemental-lib’),’template’=>’templates’);

As expected it will look for javascript files in modules/helpsystem/js, but PHP includes can be found in multiple subdirectories. Search order will look into local directory first, then into amodules3 then into any other directories you might add. So if you are writing admin system, which is located inside subdirectory “admin” but you want to use resources from one level up:

		$this->addLocation('..',array(
			'php'=>array('lib','addons'),
			// do not import pages from main
			'js'=>'templates/js',
			'banners'=>'banners',
			'logs'=>'logs',
			'dbupdates'=>'docs/dbupdates',
			))

			->setBasePath(dirname(dirname(dirname(__FILE__))))
			->setBaseURL(dirname($this->api->pathfinder->base_location->getURL()));
			;

setBasePath and setBaseURL will instruct how to access that directory. Instead of defining base paths you can also define parent location. Take a look at amodules3/lib/Testing.php

	$this->api->addLocation('test',array('page'=>'page'))
		->setParent($this->api->pathfinder->atk4_location);

This will instruct new location that it is actually a sub-location of atk4_location. Therefore URL and Path will be calculated in relation to that location by adding ‘test’ (as first argument to addLocation). By the way, you can use $api->add(‘Testing’), which will include this new location. This should give you some idea how you can add external plugins, and how you can attach them. Really simple.

As you saw in the code, pathfinder registers itself under $api->pathfinder. It will contain 2 properties – base_location and atk4_location. They are objects, however you can use them as strings. Code should be well commented, so feel free to browse.

Finally – how you can actually locate something?

$relative_path=$api->locate('php','myfile.php');
$url_to_js=$api->locateURL('js','myplugin/myplugin.js');
$log_dir=$api->locatePath('logs');      // full path to log directory

All internal components are rewritten to use new location engine. Location engine is therefore mandatory and is the first class API is going to initialise.

Windows users (who lack symlinks) should be happy too. By default system properly finds a physical path of amodules3 directory and it assumes it’s location on the web in /amodules3. If that’s not true however – you can change this through config variable $config['atk4']['base_path']=’/admin/amodules3′. Of course it’s optional setting.

Notice: BASE_PATH, AMODULES3_LIB and other defined constants are no longer set. Do not use them and try to take out paths from config file.

URL and getDestinationURL imported

Right, getDestinationURL is now implemented as object. I was already explaining about that. No big changes are here, except that this will allow more methods accept either page names your pre-formatted URLs.

$this->api->reload(‘mypage’);
$this->api->reload($this->api->getDestinationURL(‘mypage’,array(‘foo’=>’bar’));

LoremIpsum

You can now call setLength($paragraphs,$words). This should help you to get just the right amount of filler-text for your UI.

What changed?

add* methods

As I have mentioned before, we are trying to improve consistency through the library. Methods starting with “add” will now be returning new objects instead of $this. It might affect your code severely especially with addField() chains in forms. $f->addField() is returning filed now. For that reason I was able to severely clean up Form, it does not need to route calls such as setValueList().

For the same reason some methods are renamed, in particular $form->addCondition() and $form->addConditionFromGET() are renamed into $form->setCondition() and $form->setConditionFromGET(). Those methods are returning $this and are properly chained. Name is changed to reflect this.

There are no temporary compatibility for this.

Conclusion

I welcome you to try the new branch. I am going to port two projects of ours to this new branch. Please report any problems here or through mantis and I’ll deal with them asap.

2 Comments

Svetlozar Kondakov
Posted May 5, 20104:33 pm

I like the new PathFind class. It really clears out the load.php stuff and its easy to setup paths in amodules way.

However it would be strange for me to use the new result from add* .. I was used to use the $form->addField->addField syntax.

I hope this change is for good :)

romaninsh
Posted May 5, 20106:58 pm

Hi Zak.
Yeah, even through many developers were unhappy about inconsistency about function naming – many people got used to it. However new approach promotes you to enhance each field which makes forms really nice. Check this code:

$f->getElement('shop_url')->add('Button',null,'after_field')->setLabel('Verify URL')
->js('click')->univ()->newWindow($f->getElement('shop_url')->js()->val());
// here we are adding button after the field, and binding action to it.

$f->addField('readonly','items','Items')->add('Button',null,'after_field')->setLabel('edit');
$f->dq->field('(select coalesce(round(sum(quantity)),0) from wish_list_spec where wish_list_id=wish_list.id) items');
// here we are adding button "edit" after the field, which is not functional yet.
// we also add code to show number of items

$f->addField('readonly','order_price','Order price')->add('Text',null,'after_field')->set(' USD');
$f->dq->field('(select coalesce(sum(price),0) from wish_list_spec where wish_list_id=wish_list.id) order_price');
// here we are adding text after the field saying USD. Again - this should work perfectly even if you reload field.

$f->addField('readonly','shipping_price','Shipping cost')->set('3.00 USD');
// oh and btw if your field supports some extra cool functions, you can access them directly from here.

In old approach form had to proxy all those requests into last_field, which was really problematic to keep up.