@export(Contribute.Component)

Component

\Fresh\Component is the base class. It holds the views, a handler, and other settings that need to be global. It also processes form submissions before passing to your submit handler.

@export(Class.Component)

Create a component

new \Fresh\Component($name,$dir); I'm not actually sure what the name is used for, if anything.
If you extends \Fresh\Component, you can declare $name and $dir as protected properties then one does not need to be supplied via the constructor

@export(Feature.uploadFile)

Uploading files

To enable automatic file uploads, call $component->setUpload($storageDir, $urlPrefix). You are responsible for routing that file.
The $urlPrefix is used to prepend the file-url when passing formdata to your submit handler

@export(Feature.getView)

Load a view

The $passthru will be extracted so the the view file can access values directly by their keys.
$passthru is optional.

$compo = new \Fresh\Component($componentName, $componentDir);
$passthru = ['id'=>1];
$viewName = 'Note';
$view = $compo->view($viewName,$passthru);
echo $view;

This will load the file at $componentDir/view/$viewNameView.php. To be clear, your view file must end in View.php`

@export(Feature.getForm)

Load a form

The $passthru will be extracted so the the form file can access values directly by their keys.
$passthru is optional.

$compo = new \Fresh\Component($componentName, $componentDir);
$passthru = ['id'=>1, 'submit_url'=>'/submit/myform/'];
$viewName = 'Note';
$view = $compo->form($viewName,$passthru);
echo $view;

This will load the file at $componentDir/view/$viewNameForm.php. To be clear, your form file must end in Form.php`.

@export(Feature.filterSubmission)

Filter submitted data

I haven't tested this, and I don't trust it. But here's my best notes on it.

This uses a filter handler, which you set by:

$compo->setFilterHandler(
    function($name, $value, $input){
        //modify the value, like normalizing a phone number
        return $modifiedValue; 
    }
)

I'm confused, and not 100% sure how this works in practice.
Anyway, for a $_POST['somekey'] = 'some value';, there should be an <input name="somekey" /> in the source form.
Your filter handler will be called as $filter('somekey','some value', $domInputNode).
If there are multiple filter handlers... it might break.

@export(Feature.submission)

Submitting data sort of automaticallyish

You must still set a submit handler like so:

$myDbObj = get_my_db_instance();
$compo->setSubmitHandler(
    function (string $tableName, array $dataToSave, $itemId) use ($myDbObj){
        $myDbObj->save($tableName,$dataToSave,$itemId);
    }
);

@export(Feature.setup)

Routing, Setting things up

Use the setup step to do routing, basically. This requires you to append setup code to views. Here's a simple (bad) example:

$phpCode = '<?php if ($url=='/')echo $this; ?>`
/`$this` refers to the view which is being setup.
$view = $compo->view("Page_Home"); //this points to $compoDir/view/Page_HomeView.php
$view->appendSetupCode($phpCode);

This setup code must be appended pre-compile or inside a compile handler.

Then to execute your setup:

$compo = new \Fresh\Component($name,$componentDir);
$forceRecompilation = true;// good when developing. Bad for production.
$compo->compile($forceRecompilation); //  Defaults to false, if you don't pass a paramater
$passthru = ['url'=> cleanMyUrl( $_SERVER['REQUEST_URI'] ) ];
$compo->setup($passthru);

All your setup code will be run, in no particular order, and your Page_Home view will be displayed when yoursite.atld/ is requested

@export(Method.parseLookupStr)

Handling rb-find parameter.

You can write rb-find in any way you want, but the built in idea is a simple list of key1:value1;key2:value2;
call $compo->parseLookupString($find) to break those into an array.

If your key or value contains a colon (:) or semi-colon (;), that'll probably break things.

@export(Feature.compile)

Compiling

Call $compo->compile(true) to force re-compilation of all views & forms. Call $compo->compile() to use the default $forceRecompile value of false to only compile views that have changed.
You should use true in development probably.
I've had troubles with conditional recompiling (passing false) on my localhost, and I think it was because of file permissions issues, but I'm not sure.

And you can set a host of your own compile handlers.

@export(Handler.filter)

Submission Handler

@export(Extend.runtimeHandler)

Runtime Handlers

Use $compo->setRuntimeHandler(...) or $compo->addRuntimeHandler($handlerName,$function). What the handler receives varies greatly.
setRuntimeHandler will only allow one handler per $name & the callback's value will be returned when the runtime handler is called. addRuntimeHandler will allow multiple handlers. When the named handler is called, each callback's value will be stored in an array & that array will be returned.

Noteable runtime handlers:

  • find: function($table, $findProperty){return $anArrayOfObjects};
    • This MUST be declared to use the entity features
  • format_formatterName: function($value){return convertToMyFormat($value);}
    • $compo->setRuntimeHandler('runtime','format_'.$formatterName,$callback);
    • or $compo->view($view)->addFormatter($name,$callback)
  • addResources: `function($viewObj, $resourcesList){...use your framework or whatever...}

@export(Extend.compileHandler)

Compile Handlers

These will be run during the compile step.

NEED TO REDO THIS DOC FOR COMPILE HANDLERS

Use $compo->addCompileHandler($handlerName,$function). What the handler receives varies greatly.

Noteable Compile handlers: (name: Callable example)

  • preDoc: function($cleanSource,$viewContent,$compiler,$view){ return str_replace('<bad-tag', '<good-tag',$cleanSource); }
    • This runs before the RBDoc (DOMDocument) instance is created
    • Generally, you should return a modified version of the $cleanSource
    • $cleanSource is the view's source code with the PHP extracted by $compiler
    • $viewContent is the view's source code, with inline PHP still in tact
    • $compiler is an instance of \RBDoc\Compiler, which extracted the php
    • $view is an instance of the view object
  • form: function($formViewObj,$doc,$compiler,$formNode){$formNode->setAttribute('action','/some/url/');}
    • Return values are discarded, but you can modify the objects.
    • I'm not sure, but some things might be overwritten by this library, such as the action or method attributes on the node.
    • $formViewObj is an instance of \Fresh\Form
    • $doc is \RBDoc instance
    • $compiler is an \RBDoc\Compiler
    • $formNode is an \RBDoc\Node (DOMElement) instance, who's tag is <form ...>

@export(Feature.viewQueries)

View Queries: A compile handler

In my Liaison Package, I use this for routing. Here's a simplified version.

$compo->addViewQuery('//lia-route', //runs on every `<lia-route` tag
    function($rbDoc, $view, $compiler, $node){
        $route = $node->getAttribute('pattern');
        $escRoute = var_export($route, true); // because `$route` is only available during this compile step. 
        $phpCode = '<?php if ($url==$escRoute)echo $this; ?>`
        $view->appendSetupCode($phpCode);
    }
);

This function will be run during the compile step for each <lia-route tag your view contains. No errors if not found.
It will append setup code that does routing.
Then when you call $compo->setup['url'=>$theUrl], the setup code will run and your view will be displayed if the route matches the url.

@export(Handler.Compile.Form_Entity_Loop_Start)

Call $compo->addCompileHandler('Form.EntityLoop.Start', $callable)
$callable should:

  • Accept NO paramaters
  • Return a string of valid PHP code
    • DO NOT include open & close tags @ beginning and end of your code.
      • You MAY close & re-open amidst your code.

@TODO Maybe pass some paramaters to the callable???

@export(Class.Handler)

Handler is the source for extensability. You can set a handler either on the component & it will propagate, or set it directly on a view.

@export(Internals.Handler)

Doing $handlerObject->compile will get an array of handlers in the 'compmile' domain, via the __get magic method.
Then: return (object)$arrayOfHandlers... SO you have, simply, a cast object.

TODO Create a HandlerDomain object that has magic methods to make calling more dev-friendly
For each handler, if the handler was set with setHandler()... you can $handler->compile->$HandlerName()... and get a return value
If the handler was put with addHandler()... Then $handler->compile->$HandlerName returns an array of handlers, which can each then be called.

@export(Contribute.readonly)

A cute little trait to allow for public-read-only properties on a class

Declare:

use Fresh\Readonly;

protected $property; // Publicly, do `$theClass->property` to retrieve... though the public cannot set it.
private $r_property; // This instructs the trait.

@export(Handler.Compile.View_Entity_Loop_Start)

Call $compo->addCompileHandler('View.EntityLoop.Start', $callable)
$callable should:

  • Accept NO paramaters
  • Return a string of valid PHP code
    • DO NOT include open & close tags @ beginning and end of your code.
      • You MAY close & re-open amidst your code.

@TODO Maybe pass some paramaters to the callable???

@export(Handler.Runtime.addResources)

If your view has any resources associated, you must register an addResources handler.

  • addResources: `function($viewObj, $resourcesList){...use your framework or whatever...}
    • $resourcesList is in the format ['php'=>$arrayOfFiles,'js'=>$arrayOfFiles,'css'...] & so on for EVERY file that is associated with your view.
    • These files are found at YourViewNameView/some_file.EXTENSION
      • I think you can do YourViewNameView.css and YourViewNameView.js as well
      • It also works with YourViewNameForm/files....

@export(Internals.executeCompileHandlers)

Calling $viewRoot->executeCompileHandlers($handlerName, ...$argsForHandler) will return an array of return values from the called handlers.