TODO.Scanner

  • allow configuration of the prefix regex
  • Class property to auto-merge with built-in prefixes
    • As an alternative to overriding getApiPrefixes()
  • Document how to use prefixFor()

TODO.RouteObject

  • Document the route object

TODO.View

  • Config to set a namespace for all views of a given package
  • perhaps $lia should be a required paramater, not hidden in an array
  • Add an init + template approach like view/Blog/template.php and view/Blog/init.php
  • Add automatic routing via the view system (which is more robust and neat than simple public-files), such as with a public-view dir
    • a ` might be a valid option, but that seems more like an extension feature than a core feature
  • Document what paramaters are always available to views
  • Document an example of a view file's code (such as the example blog.php view)
  • For sibling resource files (view/blog.php, view/blog.css, view/blog.js), resources() returns '.js' and '.css' for the resource files.
    • Maybe they should have real names? But the current setup prevents conflicts between view/blog.css and view/blog/blog.css
  • Document resources() function & returned array

Old.View.Base

The View Object

  • Each package can implement their own view object and method of handling data. The following docs regard \Lia\View, used in the base package.
  • Generally, retrieve a view through liaison or the ViewHandler component.
    • You may also do new \Lia\View($viewPath,$data,$liaisonObject,$viewName=null), such as if you're creating your own package implementation.
  • Data passed in (through lia OR the constructor) will be extract()ed
  • The content is loaded in the constructor
  • Resources are loaded into liaison during the constructor. So you just call $lia->view($viewName), if all you want is to use the associated css & javascript resources. Display your view with echo $view

View Structure

We have a view named "Form/Blog" at view/Form/Blog/. All your views go in the view directory and the path to the relative path to the view is it's name.

view/Form/Blog/
 - init.php: (optional) code to run before the template
 - template.php: (recommended) The PHP file to load, this is your html layout for the most part
     - template.php & init.php are in the scope of the \Lia\View object that loads the files. Therefore, `$this` refers to the view object
     - $lia, the Liaison object, is also available
     - Uninentionally, $viewPath, $data, $viewName, & $path are available, but you should not rely on them. They will likely be removed.
 - template.html: If a template.php file is not present, then template.html will be used.
 - css/ (optional)
     - BlogEditorStyle.css
 - js/ (optional)
     - BlogAutosaver.js

You don't actually have to have a template. css & js resources will still load

Every css file in the css dir will be found and added to liaison through the Red_AddStyleFile event, which passes the absolute file path along to the event. Same for js, but Res_AddScriptFile.

Utility.FancyClosure.TODO

@TODO add check to see if a callable is actually callable @TODO setup read-only properties

Utility.FancyClosure

Fancy closures enable binding of paramaters to a callable and inspection of callables, whether as ['\\StaticClass','functionName'], [$object, 'methodName'], or $anonymousFunction = function(){}. Example:

$cat = new \Funny\Cat();
$loudness = 7;
$closure = new \Lia\Utility\FancyClosure([$cat, 'purr'], [$loudness]);
$closure->funcName === 'purr';
$closure->object === $cat;
$closure->class === 'Funny\\Cat'; //it prints with a single slash, but backslashes are generally better off being escaped in my experience
$closure->isStatic === false; // would be true if using ['Funny\Cat', 'purr'] instead of [$cat, 'purr']
$closure->isAnonymous === false; // would be true for function(){echo 'Kindness can be anonymous too.';}
$closure->function === null; // would be the anonymous function, if you had passed a function instead of an `[$obj, 'funcName']` callable

$closure->origCallable === [$cat, 'purr']; //just the first arg you pass to the constructor
$closure->bound === [$loudness]; // and this is the 2nd arg

TODO.Package

  • Implement an 'api name' for retrieving packages, prefixing view names, public files, etc
  • Revisit lifecycles. There's a lifecycle component, but that doesn't really handle packages... Idunno. I'm confused by it

OLD NOTES

  • document the public dir
  • document the file-to-pattern conversion
  • document url normalization
  • Document changing the view class
  • Document general package usage
  • Document creating a custom package

Usage.Router.publicDir

Files in the public dir of your package will be automatically routed to.

  • public/index.php files will be delivered without the file name or extension
  • public/dir/file.php files will be delivered at /dir/file/
  • public/resource.js and other non .php files will be delivered at /resource.ext

There's much more to document and features to set up with routing, still.

Usage.Package.DefaultConfigs

protected $config = [ 'dir'=> [ 'component' => 'core', // 'public' => 'public', 'autoload'=> 'class', 'view' => 'view', 'cache' => 'cache',

        'public'=>[  // @TODO rethink config structure. public maybe shouldn't be nested under dir? Idk....
            'dir' => 'public',
            'baseUrl'=> '',
        ]
    ],

'route'=>
    [
        'force_trail_slash'=>true,
        'index_names'=>
        [
            'index'
        ],
        'hidden_extensions'=>
        [
            'php'
        ],
    ],
'class'=>
    [
        'view' => '\\Lia\\Obj\\View'
    ],
'views'=>
    [
        // 'conflict' => 'throw'
    ]

];

TODO.Autoload

  • Add classmap-autoloading method (currently only PSR4 is supported, I think)
  • Cache autoloader classmap to disk

TODO.Error

  • Figure out how to do error handling...

Usage.GlobalParams

Call $lia->addGlobalParam($argName, $value);, then in your views and public files $argName will be available.

TODO.Resources

Maybe not so difficult

  • Use config for default site title
  • move SEO code into it's own component
  • Auto-add charset=utf8 & viewport meta tags (with config to disable)
  • Add url prefix for compiled files as a config option

Maybe not so simple

  • Consider using custom routes instead of storing files in a cache-public dir
  • jsFiles & cssFiles arrays have the full file path as their key & value. Add ability to name the paths. This will improve dev experience when sorting a list of scripts/stylesheets
  • Improve sorting
    • add sort preference to addResourceFile($file). A Liaison extension that adds a JS framework would use this to ensure it's framework file is always the first thing.
      • Without this, the sort burden is on the developer who is integrating the Liaison extension.
    • Add a simple function for setting sort preferences, like $lia->showFirst('*autowire.js'); or something
  • Consider other methods of routing that might improve performance...
  • add all seo meta properties that are available...
  • Separate large files from the block of compiled code.
    • If i'm using a, say, 50KB or larger JS file on 10 different pages, but each of those pages has a couple different small JS files for their individual components, it's probably better to cache the 50KB file on its own
  • Minify js & css

TODO.Router

Documentation

  • Document the paramaters that are passed to a public file
  • document examples of routing
  • improve 'Pattern Rules' documentation

Essentials

  • figure out sitemaps... Though that may not be part of router??
  • add... something to help convert pattern-based routes to sitemap representations

Performance

  • caching of urls & routes

Other

  • auto-add public dir for each package
    • Right now, the package handles this. Should the Router be able to process a directory? (probably)
  • add a function to convert a file path to a pattern (aka, remove extensions like '.md' and '.php', per a configuration)
  • add a normalizeUrl function (add trailing slash, remove .php / .html / .md, all lowercase?)
  • Option to return both perfect-match routes AND routes that match with the normalized url, aka: /some/url && /some/url/ would return the same route(s)
  • add a mediator function to handle multiple global routers, possibly??

Usage.Router.addRoute

Call $lia->addRoute($pattern, $callbackOrFile,$package=null) to add a route to the built-in router

@param $pattern A pattern. See [the pattern matching rules](@link(Rules.Router.pattern))
@param $callbackOrFile a callback or a file path
@param $package (optional) A liaison package

Usage.Router.getRoute

Rules.Router.pattern

rules:
    .php will generally be removed & replaced with a trailing slash, but that is NOT part of parsePattern()
    That will be a pattern-normalization step that happens prior to parsePattern() and is extensible/configurable

    Methods: @POST, @GET, @PUT, @DELETE, @OPTIONS, @TRACE, @HEAD, @CONNECT
        - We do not currently check the name of the method, just @ABCDEF for length 3-7
        - These must appear after a `/` or after another '@METHOD.' or they will be taken literally
        - lower case is not valid
        - Each method MUST be followed by a period (.)
        - example: /@POST.dir/sub/@GET.file/ is valid for both POST /dir/sub/file/ and GET /dir/sub/file 

  Paramaters:
      - {under_scoreCamel} specifies a named, dynamic paramater
      - {param} must be surrounded by path delimiters (/) OR periods (.) which will be literal characters in the url
      - {param} MAY be at the end of a pattern with no trailing delimiter
      - {paramName:regex} would specify a dynamic portion of a url that MUST match the given regex. 
          - Not currently implemented
      - {?param} would specify a paramater that is optional
          - Not currently implemented
    examples: 
        /blog/{category}/{post} is valid for url /blog/black-lives/matter
        /blog/{category}.{post}/ is valid for url /blog/environment.zero-waste/
        /blog/{category}{post}/ is valid for url /blog/{category}{post}/ and has NO dynamic paramaters

TODO.Server

  • Graceful fallback for when view() is not available
  • Graceful fallback for when 'theme' view is not available
  • When route is a callable, should the callable output content or should it return content that is echo'd by Server?

TODO.ViewComponent

  • document the use of a view that does NOT implement Lia\IView
  • implement & document adding a view by simple file path

TODO.Cache

  • Consider adding defaultExpiry as a config, rather than a default paramater in the cacheFile() function call
  • Add a key=>value cache that returns values instead of file paths
  • probably auto-delete if an expired file is requested
  • Possibly add lia.cacheDir.public & lia.cacheDir.public.baseUrl to assist in routing
  • Are these the same thing?
    • Consider function to return file content, not just file path. Consider additional decoding like parsing json or yaml.
    • Consider adding type-based processing (PHP, JSON, DOMDocument??)
    • Consider extensible features (such as auto en/decoding additional types not supported by Liaison)
  • cache response of getCacheFile() so files don't have to be loaded more than once