SitePoint Sponsor |
|
User Tag List
Results 101 to 125 of 138
-
Apr 15, 2005, 05:27 #101
- Join Date
- Jan 2003
- Posts
- 5,748
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
The model I have at the moment is still fragile and prone to change until I can get something concrete together to use the model and see what breaks, and where, under stress.
Unit Testing has helped in some way, but I'm not entirely happy as yet. So I've not thought about Javascript. My stance is that you put in the document HEAD the Javascript file, and use the DOM to manipulate the document based on IDs, from the client but...
This is another topic I think, as we now have rich clients using AJAX, JpSpan et al How are these effected by a recursive structure? I don't know myself at the moment.
If parent asked its children for <head> info, the child wouldn't even need to know about its parent, in which case the parent my as well be root.
-
Apr 15, 2005, 06:36 #102
- Join Date
- Jan 2005
- Location
- Sydney
- Posts
- 43
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Originally Posted by Dr Livingston
PHP Code:..... Read the XML file into an array of Actions to be called and with id + parent_id .....
foreach ($actions as $action) {
$a = new $action['actionname'];
$a->act();
$views[$action['actionname']]['view'] = $a->getView();
$views[$action['actionname']]['id'] = $action['id'];
$views[$action['actionname']]['parent_id'] = $action['parent_id'];
}
$cv = new CompositeView;
$cv->addViews($views);
$cv->run();
echo $cv->display();
I think the CV should create a big XML file by reading the ids and parent_ids and then the XSL file will be created by using <xsl:include/> and creating one XSL file including all the XSL files from each view. Then just one transform and viola nice XHTML page.
-
Apr 15, 2005, 07:55 #103
Originally Posted by dylanegan
Each view returns a xsl:template (considering more than one atm, using modes for things like javascript), that is placed in a XSLT.
Implemented so far... given a HTML template
Code:<html xmlns:tp="urn:templating.experiments"> <head> <title><tp:title /></title> </head> <body> <div id="navigation"> <tp:navigation param="1" /> </div> <div id="searchbox"> <tp:searchbox /> </div> </body> </html>
Code:<?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" xmlns:tp="urn:templating.experiments" version="1.0"><xsl:output method="xml" media-type="application/xhtml+xml" encoding="UTF-8" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" omit-xml-declaration="yes" cdata-section-elements="script style"/><xsl:template match="/"><html> <head> <title><xsl:call-template name="title"/></title> </head> <body> <div id="navigation"> <xsl:call-template name="navigation"><xsl:with-param name="param" select="1"/></xsl:call-template> </div> <div id="searchbox"> <xsl:call-template name="searchbox"/> </div> </body> </html></xsl:template></xsl:stylesheet>
Also need to investigate the how capable calling PHP from an XSLT transform is, so can attempt something like ruby components run_component
so could have
<tp:runComponent controller="gallery" action="latestImage" /> converted to <xsl:call-template name="runComponent"><xsl:with-param name="controller" name="gallery" /><xsl:with-param name="action" value="latestImage" /></xsl:call-template> with that doing
<xsl:template name="runComponent">
<xsl:value-of select="php:function(some-magic-here)" />
</xsl:template>
which'll also get xsl:include/xsl:import'd into at XSLT building stage.
-
Apr 15, 2005, 09:41 #104
- Join Date
- Nov 2001
- Location
- Bath, UK
- Posts
- 2,498
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Originally Posted by Dr Livingston
Take it all back down to the fundamentals. What you are writing is a script to take one string, and from that, output a second string. PHP does a good job at distancing you from that initial input string, but for any script you have to remember that that is where it starts, and that is where it ends.
DouglasHello World
-
Apr 15, 2005, 10:01 #105
- Join Date
- Jan 2003
- Posts
- 5,748
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Umm...
I didn't put much thought into Javascript as I'm a serverside developer, and I tend to stay away from Javascript nowadays. That's my excuse anyways
On the point of breaking it all down to the barebones, this is what I'm doing at the moment (see 'refactoring question' thread) but I'm not following your
script to take one string, and from that, output a second string.
-
Apr 15, 2005, 10:17 #106
Well, I think the problem isn't just entirely javascript. Just used it as an example.
CSS would be the another, sub-component-x requires some css rules to be available in the output.
-
Apr 15, 2005, 10:40 #107
- Join Date
- Jan 2003
- Posts
- 5,748
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I agree with you on this point, and have not found a solution either...
If, during the recursion cycle you have some kind of 'map' to map the CSS to a given composite node, ie An array for example, you could inject this array index(es) into the composite it's self, would this help?
See... http://www.dofactory.com/Patterns/Patterns.aspx
Looking at the Visitor for a moment, the Visitor could visit the composite, passing the array index along with it? This is just a thought though, I have been wrong in the past.
Hope it helps anyways.
-
Apr 15, 2005, 12:25 #108
- Join Date
- Jan 2003
- Posts
- 5,748
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Ren,
I have altered in a quick manner my original classes to accept a visitor as an example, so I hope you can follow this script.
For each composite there is, you basically want the class 'Visitor' to do your thingOkay, here goes...
PHP Code:class XmlWalker {
// see my composite post in my sig, as
// this class has no changes
}
// utils
class ApplicationFaultException extends Exception {
public function __construct( $message ) {
parent::__construct( $message );
}
}
class IllegalParameterException extends Exception {
public function __construct( $message ) {
parent::__construct( $message );
}
}
interface IParser {
public function getRoot();
public function push( $fragment ); // DomElement
}
class XmlAdaptableCompositeParser implements IParser {
private $decoratable;
public function __construct( $decoratable ) {
$this -> decoratable = $decoratable;
}
public function getRoot() {
return $this -> decoratable -> getRoot();
}
public function push( $fragment ) {
if( $fragment -> nodeName == 'fragment' ) {
return $this -> decoratable -> push( $fragment );
}
}
}
class XmlCompositeParser implements IParser {
private $root;
private $visitor;
public function __construct($fragment ) {
if( !$fragment instanceof DomElement ) {
throw new IllegalParameterException( 'thrown exception on, expected parameter(s) not found.' );
break;
}
$this -> root = new Composite( $fragment );
}
public function getRoot() {
return $this -> root;
}
public function push( $fragment ) {
$composite = new Composite( $fragment );
if( $tmp = $this -> traverse( $this -> getRoot(), $fragment ) ) {
// added this part to original class
$this -> visitor -> visit( $composite );
$tmp -> attach( $composite );
}
}
// added this part to original class
public function accept( $visitor ) {
$this -> visitor = $visitor;
}
private function traverse( $composite, $fragment ) {
$parent = $fragment -> getElementsByTagName( 'parent' );
$parent = $parent -> item( 0 ) -> nodeValue;
if( $composite -> getId() == $parent ) {
return $composite;
} else {
if( $composite -> hasChildren() ) {
$children = $composite -> getChildren();
foreach( $children as $child ) {
$c = new Composite( $fragment );
if( $tmp = $this -> traverse( $child, $fragment ) ) {
// added this part to original class
$this -> visitor -> visit( $c );
$tmp -> attach( $c );
}
}
}
}
}
}
PHP Code:...
class Visitor {
public function __construct() {
}
public function visit( $composite ) {
echo( $composite -> getId().'<br />' );
// Ren, i've only outputing a composites ID but
// you need to do what you want at this point
}
}
$dom = new DomDocument;
$dom -> load( 'test.xml' );
$fragment = $dom -> documentElement -> childNodes;
$walker = new XmlWalker( $fragment -> item( 1 ) -> childNodes );
$parser = new XmlCompositeParser( $fragment -> item( 1 ) );
// adding a visitor alters interface :eek2:
$parser -> accept( new Visitor() );
// require a decorator to filter tags by the name of 'fragment'
$parser = new XmlAdaptableCompositeParser( $parser );
$walker -> walk( $parser );
...
-
Apr 15, 2005, 13:24 #109
- Join Date
- Nov 2001
- Location
- Bath, UK
- Posts
- 2,498
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Originally Posted by Dr Livingston
You get one string in, looks something like this:
Code:GET /search?q=php HTTP/1.1 Host: www.google.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.6) Gecko/20050226 Firefox/1.0.1 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 Accept-Language: en-gb,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Proxy-Connection: keep-alive
Code:HTTP/1.x 200 OK Cache-Control: private Content-Type: text/html Content-Encoding: gzip Date: Fri, 15 Apr 2005 20:11:38 GMT <html> ... </html>
I have to admit I didn't fully grap this until I started learning to use Ruby without Rails. Ruby is much more general than PHP, it isn't focused on web development. PHP is becomming more useful for non-web things, just as Ruby and Python are becomming more useful for web things. (With Ruby, this is mostly due to Rails.)
Beyond that, the challange is to build that output string as "fast" as possible. (I've overloaded "fast" a little there. I mean fast rendering of the HTML, fast development time, fast maintenance, everything.)
WRT Javascript and CSS, I treat them much like images. I just put them in a public directory on the server, and link to them from my HTML. I try to avoid building CSS per request, the same as I try to avoid building images per request. Hell, I try and build as little HTML per request as possible too; it all fits into the "render as fast as possible with as little effort on the part of the developer as possible" idea
WRT server-side development... I don't consider myself a server-side developer, more someone who builds web interfaces. In my case, that usually involves some web design and user interface design too, though nothing I would consider "heavy" server side development, like writing database servers or web servers or anything like that.
DouglasHello World
-
Apr 15, 2005, 13:33 #110
- Join Date
- Nov 2001
- Location
- Bath, UK
- Posts
- 2,498
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Originally Posted by Dr Livingston
Looks more like you are just adding layers of complication, though I may have missed what it is you are tring to do. You might want to look at how Propel handles XML. It uses XML config files, but caches them as PHP files for performance reasons.
Personally, I just use PHP files for config anyway
DouglasHello World
-
Apr 15, 2005, 13:35 #111
- Join Date
- Nov 2001
- Location
- Bath, UK
- Posts
- 2,498
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Originally Posted by Dr Livingston
Just write the above like this:
PHP Code:class ApplicationFaultException extends Exception {}
class IllegalParameterException extends Exception {}
PHP Code://
}
}
}
}
}
}
PHP Code:public function __construct($fragment ) {
if( !$fragment instanceof DomElement ) {
throw new IllegalParameterException( 'thrown exception on, expected parameter(s) not found.' );
break;
}
$this -> root = new Composite( $fragment );
}
Why do this yourself when PHP does it for you:
PHP Code:function __construct(DomElement $fragment) {
$this->root = new Composite($fragment);
}
DouglasHello World
-
Apr 15, 2005, 13:52 #112
- Join Date
- Aug 2004
- Location
- California
- Posts
- 1,672
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
This is an interesting discussion that leads me to think that each component (I called them a "subMVC' earlier) in the heirarchy needs to not just a "view" in the block sense, but a group of related chunks that the parent can apply to build the final output. As Douglas says, the goal is just to output a string that is HTML. Following this conversation a compenent needs to send back at least two strings: one to go in the '<head>' chunk (CSS and Javascript) and one for the '<body>' chunk (HTML). So rather than just a render() function, perhaps at a minimum our View should look like:
PHP Code:class HTMLView {
function addHead() {}
function addBody() {}
function renderHead() {}
function renderBody() {}
}
Christopher
-
Apr 15, 2005, 14:11 #113
- Join Date
- Jan 2003
- Posts
- 5,748
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Doug (can I call you Doug?),
I didn't know that extended Exceptions could be curtailed like that... Need to check that now
True, there may be no need for the Composite class, since most of it's functionality resides in the Component class, but looking at the pattern, a Composite is subclassed so I followed with it.
I also like the use of instanceof to catch illegal parameters, rather than leave it for type checking to catch them. Makes me feel safer, that's all. Hope this helps mate.
-
Apr 15, 2005, 16:29 #114
- Join Date
- Nov 2002
- Posts
- 841
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I've been working on this composite view problem for the WACT controllers. I think I might have a reasonable solution soon. My current line of attack uses a ViewComposer object that is passed down the chain of responsibility represented by the controller tree. Its the not exactly the visitor pattern, but rather more like a collecting parameter pattern.
In this architecture, views house the ability to specify if they can "accept" a parent, or "accept" a child.
Movement along the chain of responsibility continues as long as the view composer 'isAccepting'. The ViewComposer continues accepting view building blocks as long as it has a place to put them (either as a parent or a child). Once the View runs out of places to accept new components into, then further processing is short circuited and the view is rendered.
There are roughly four kinds of View objects:
View - Stand alone
MasterView - accepts children
PartialView - accepts a parent
PartialMasterView - accepts a parent or a child.
A fifth kind of view, a DecoratingView, breaks some of the rules. The decorating view can accept a MasterView or a PartialView as a child and takes on some of the characteristics of the child in regards to the algorithm. These are used for meta-things like output caching, model building, and HTTP headers. Some of the things one might use intercepting filters for.
There are still some round peg, square hole type conflict resolution issues to work out. Mostly, I am leaning toward throwing out the old structure and starting a new one when a conflict occurs.
The algorithm I am focusing on is somewhat counter intuitive in that it builds the composite view from the leaves first and root last. It turns out there are some performance advantages to this and perhaps some usability advantages for the framework users. Its early to say.
There are drawbacks. For one, forwards are becoming extremely difficult, if not impossible to implement. In other threads I've postulated that forwards are how nonhierarchical frameworks clumsily simulate hierarchy. Wouldn't it be ironic if turned out that hierarchical frameworks ended up having to clumsily simulate forwards? Anyway, I am hoping that forwards don't prove necessary.
I think the key to pulling this off in the long run is relative addressing. Each component (M, V, or C) must address its neighbors in a relative way or you can never use it out of context and so there would be little gain in busting your application up into tiny little pieces.
There are alot of implementation details to work out, but so far, I think the concept is sound.
-
Apr 15, 2005, 16:34 #115
- Join Date
- Jan 2005
- Location
- Sydney
- Posts
- 43
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Heya Ren,
The last bits you mention about calling a particular action or such. I am planning on using PHPTAL for this as it will all be done in the model area so the view only recieves XML data.
An example would be form management (I started a thread a while back) which would use something like <ns:form name="name"/> this would convert the form into the XML that is defined and if there are any current values, validation errors and so on it would grab them and parse them into the form and then once this result is passed to the view the view would have appropriate XSL to transform that into XForms, Web Forms 1/2 or what ever I would like.
-
Apr 15, 2005, 17:48 #116
- Join Date
- Aug 2004
- Location
- California
- Posts
- 1,672
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I've been working on this composite view problem for the WACT controllers.
The View is very dependent on the template system used and the Model on the pattern/system used in the data layer. But the Controller has more dependencies which makes it interesting.Christopher
-
Apr 16, 2005, 04:49 #117
- Join Date
- Jun 2003
- Location
- Elsewhere
- Posts
- 107
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Originally Posted by Selkirk
Originally Posted by Selkirk
Fetch- Data - the Action returns its filtered data.
- Block - the data is also parsed into a template, and the output is returned.
- Main - data is parsed, a document device is fetched, and the block output is merged into the document template. The document is returned.
Process- Main - see above.
- Subprocess - the Action is performed, but nothing is returned.
There's a document device for each type of action: document_fetch, and document_process. Fetch uses the regular website template, process uses a redirection template. The data of each processing Action contains a reference to where the user should be taken next.
Originally Posted by Selkirk
PHP Code:class smsDeviceFactory
{
public static function buildDevice( $deviceData )
{
$class_name = $deviceData['config']['class']['name'];
$device_name = $deviceData['config']['device']['name'];
$device_module = $deviceData['config']['device']['module'];
if ( !class_exists( $class_name ) )
{
$class_module = $deviceData['config']['class']['module'];
$class_path = 'app/'. $class_module .'/source/';
smsPath::readClassFile( $class_name, $class_path );
}
// Create device
$device_instance = new $class_name( $deviceData['config'] );
return( $device_instance );
}
}
PHP Code:$UserStorage = $this->getDevice('storage_user');
This solution is rather complicated, but I no longer have to pass devices from one to the other, because everything can be pulled. It's also possible to use only parts of the application, because each device is completely self-sufficient: it can solve its own dependencies, and gains all the knowledge it requires from its configuration.
-
Apr 16, 2005, 09:28 #118
- Join Date
- Sep 2003
- Location
- Glasgow
- Posts
- 1,690
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
There's something about parent-child designs which makes me uneasy. Would you say that knowledge about the structure of the browser page is leaking out of the presentation layer?
-
Apr 16, 2005, 09:49 #119
- Join Date
- Aug 2004
- Location
- California
- Posts
- 1,672
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
There's something about parent-child designs which makes me uneasy. Would you say that knowledge about the structure of the browser page is leaking out of the presentation layer?
I think the comments on "relative addressing" are interesting. I have been using a Service Locator for some of this and found it works well.Christopher
-
Apr 16, 2005, 11:53 #120
- Join Date
- Sep 2003
- Location
- Glasgow
- Posts
- 1,690
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I'll need to waffle a bit before making my point.
In Cartesian dualism, a distinction is made between internal mind and an external reality. In programming, clear Cartesian boundaries between an internal application mind and external inputs/outputs are I think fundamental to good design. The data access layer is one and the view is another. With well-defined boundaries, the application "core" can use a variety of data sources and output in a variety of formats.
Composite views use template fragments rather than a unified, whole page template but all formatting knowledge, I think, belongs on the other side of the view boundary. The application can present a set of data without knowing anything about how that will be used to build a page.
When you include a template, you cross the boundary. Now you're in a whole new realm with a different skill set - html design if it's an html page. Html designers have their own tools to manage shared layout elements: the app doesn't need to concern itself with that at all. There's still some more php to come in looping through rows, conditionals, or simple echoes but the template engine is really a whole other app in its own right.
Composite data-gathering code would be OK and that's where I'd stop. All knowledge about shared headers, footers or etc should perhaps exist only on the other side of the boundary. Apart from code design issues, it makes life a whole lot easier for designers who no longer have to work with fragmented pages.
We're talking without reference to any real code of course: I don't know WACT well enough to say if this is a valid concern.
-
Apr 16, 2005, 12:45 #121
- Join Date
- Jan 2003
- Posts
- 5,748
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Composite views use template fragments rather than a unified, whole page template but all formatting knowledge, I think, belongs on the other side of the view boundary.
Please, waffle on...
-
Apr 16, 2005, 13:20 #122
Originally Posted by McGruff
Im currently toying with having templates (even sub components) being entire/complete/validatable html page. So each component can have its own javascript & css etc, which eventually all gets merged.
So a designer can open any template in some sort of wysiwg tool.
Also opens up the possibility of using iframes for giving previews to composite views.
-
Apr 16, 2005, 13:29 #123
- Join Date
- Aug 2004
- Location
- California
- Posts
- 1,672
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I'll need to waffle a bit before making my point.
Composite views use template fragments rather than a unified, whole page template but all formatting knowledge, I think, belongs on the other side of the view boundary. The application can present a set of data without knowing anything about how that will be used to build a page.Christopher
-
Apr 16, 2005, 14:04 #124
- Join Date
- Jun 2003
- Location
- Melbourne, Australia
- Posts
- 440
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Originally Posted by Selkirk
I think the key to pulling this off in the long run is relative addressing. Each component (M, V, or C) must address its neighbors in a relative way or you can never use it out of context and so there would be little gain in busting your application up into tiny little pieces.Zealotry is contingent upon 100 posts and addiction 200?
-
Apr 16, 2005, 14:19 #125
- Join Date
- Sep 2003
- Location
- Glasgow
- Posts
- 1,690
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Originally Posted by arborint
Originally Posted by arborint
Often you'll find that bits of data cut across page elements: eg a page title might be output in a header and in the < head > html. Gathering data for a page in a structure which mirrors the page layout can make it more awkward to share.
Incidentally you could identify another boundary - an input boundary - in the presentation layer which might provide the flex point for an easy switch between http and CLI. Any place where there is input or output there's a Cartesian boundary.
PS: I started off by wondering if information about page structure was leaking out of the presentation layer. What I meant to say was is it extending too far into the view.
Bookmarks