Escher was a PHP MVC framework developed by Thom Stricklin from 2011-2013. Escher implemented a hybrid of Model2 MVC and PAC architectures and CMS concepts as well as plugins and configuration wizards. Development halted in 2013 in favor of Kohana and later Symfony, which closely aligned to the same design principles as Escher.
The following error occurs:
Fatal error: Call to undefined method Model_upload::saveUploadedFile() in /var/escher/controllers/uploads/controller.uploads.php on line 13
Invalid authentication request occurs when signing up for a new account when using Facebook and Twitter. (The Account gets created in the DB, but Invalid authentication request occurs every time you try to log in).
For users who already had a Facebook or Twitter account, logging in via Twitter or Facebook works.
Edit
To clarify, the user gets an entry in the user table, but not in user_metadata or user_content
getPathByInstance($controller,$id=NULL,$absolute=TRUE)
Returns the URL string of the path corresponding to the given controller/id.
getRoute()
Returns the $route model
resolvePath($url,$absolute=TRUE)
resolves a relative path optionally containing shorthand notation to an absolute path (or, if $absolute==FALSE, a path relative to the root of the Escher installation)
Input status will allow the ability to set the callback information on input fields returning a JSON reponse. This method will have name, type, and message.
Name will be the field name and type will be (error, success). Getting the input status will simply return the JSON response for the field names that are set using the set method.
Provide a way to set the return path after successful authentication using Facebook, Twitter and Google Plugins or a way to return to the current page.
A use case would be if a login action was called from a page or modal and upon successful login, it would return to that page that initiated the login.
The format of model input names, instead of page_123_title, can be model[page][123][title].
New model inputs can be model[page][new][uniqid][title].
Perhaps $model->parseFormData() can be renamed to $model->parseInput().
Also, model views with fields need to conform to some structural standards (to make them compatible-ish with Bootstrap). Ideally using $HTML, $UI, or some other helper.
Metadata and content values are currently stored as EAVs in unstructured tables. This is an anti-pattern that imposes severe limitations on the ability to access and manipulate these fields at an SQL level.
Propose to instead move to a consistent, one-model-per-row approach for metadata and content tables just as it is for a model's primary table. Storage location for a field will be determined by the schema:
TEXT/BLOB and related fields will always go into model_content.
Fields flagged as "metadata" => TRUE will be stored in model_metadata.
All other fields defined in the model schema will simply go into the main model table.
This behavior will be partially reversed for fields registered via plugin hooks:
Fields must be explicitly flagged as "metadata" => FALSE in ordered to be stored in model; by default, they will be stored in model_metadata.
Additionally, hooked fields will not be able to override/alter a default model schema field, to preserve the default data and functionality of the model.
Code in the Escher core currently depends on $router->getPath(), either directly or indirectly (e.g. $this->path inside a controller). This should be revised to use the new functions.
Additionally, $header->redirect() should be modified to use the $router->resolvePath() function.
Default password encryption is the password encryption currently used by the auth type. (i.e., sha1 or md5)
Preferred password encryption is what the passwords will be converted to if not using this encryption type.
In many cases, getSitePath() and getRootPath() will return the same result. However, if a self-contained site has been declared in the routing structure of the installation, getSitePath() will refer to the root of the declared site, not the root of the Escher installation.
Add to controllers a protected function $this->dispatch() that will route subrequests to another controller. Arguments could take the following format:
...where $subcontroller is a string of the (hookable) name of the subcontroller, args is an array of arguments to pass to the subcontroller, options is an associative array of options to provide the subcontroller, and display is a boolean determining whether the function should return rendered results (default) or display and exit.
An example of dispatching actions to a $subcontroller would be:
I'm still debating as to whether or not there's a better way to handle $options, whether $display is necessary, or whether dispatch() should be split into multiple functions. Part of me thinks $options is a good thing, but might result in some changes in other places (e.g. $route->instance_id). Now taking suggestions! :)
Models used to only check for metadata (or content) if $m->_metadata/$m->_content were TRUE or non-empty arrays. This was changed to accommodate metadata that might exist for disabled plugins. However, I think this can be handled more efficiently without risk of losing "disabled" data:
Only check for metadata/content if $m->_metadata/$m->_content are non-empty.
Append "living" schema with metadata/content fieldnames. This will prevent content from being deleted on next save.
Only set metadata/content if $m->_metadata/$m->_content are non-empty.
The relationship between controller properties and router properties is a mess. Dispatching needs to assign options straight to a controller, but in "regular" requests, the controller tries using properties from the router.
Also, id vs. instance_id vs. model_type and model_id need to be reconciled.
Possible todo: add $router->getController() method for doing the handshake (escher/index.php:67)? Or should this just remain in EscherInit::main()?
Right now, it's a bit cumbersome to implement HMVC. Specifying subcontrollers that can be dealt with directly by the execute() function would be a nice addition.
The execute() function would look for the presence of $arg[0] as an array key in $this->subcontrollers, and if present load the correct controller and pass the remaining args on to its own execution.
There could even be a hook for adding subcontrollers, although the usefulness might be limited without deeper functionality.
It would be awesome to create the ability for views to be "extended" along with controller classes.
Example: I want to create a modified version of the "blog" controller.
The new "myblog" controller would extend the "blog" controller.
I might modify an action or create a new action, but most functionality would remain the same.
Similarly, most views could remain the same.
However, because views are physical files, at present they must be copied into the views folder of the new controller.
The process of "extending" views can be done at the object level by tracing its own class inheritance until it finds the requested view (or hits a stop).
I have have a small success rate, it works one time, then it just stops working.
I try doing a die_r($this->save()) on the Model_user::register() function and it is empty. I am not sure what is causing the error, I am at a loss.
This only happens on Facebook and Twitter, it does not happen with local registration. The registration vars do get assigned properly, but saving never occurs, it does fire the hook register_error, No server errors, no php errors/warnings. I turn off memcached, and it still doesn't register.
Twitter and Facebook plugins using $user->id instread of $user->user_id.
Facebook registering model plugin for facebook_full_name instead of facebook_display_name
Create a dynamic router, one that will traverse a database-driven heirarchy of route nodes in parent-child relationships (resolved by parent id and route tag).
Attempt to find route among static routes first.
If no static route matches, attempt to recursively load dynamic route model (based on parent/root id and next url component) until no model can be found.
If absolutely no model can be found, return false and fall back to root functionality.
<div class="clearfix">
<label>Username</label>
<div class="input">
<input type="text" name="username" />
<span class="help-block">Note: Username must be 5 or more characters.</span>
</div>
</div>
Current ACL check()/req() is inefficient for contexts and entities with many ancestors (e.g. dynamic routes, users with many group memberships). Current efficiency is O(n*m).
Refactor ACL so that check() efficiency is O(n+m) or better.
Warning: array_merge(): Argument #2 is not an array in escher/helpers/datasource/db/helper.datasource.db.php on line 287 Warning: array_merge(): Argument #2 is not an array in escher/helpers/datasource/db/helper.datasource.db.php on line 287
(mysqli): SELECT * FROM acl_rule WHERE (resource_type = 'all' AND resource_id = '0')
AND action = 'all' AND context IN('/',0) AND ((context = '/' OR inheritable = 1)) AND
(((entity_type = 'user' AND entity_id IN(1,0)) OR ()))
Query: SELECT * FROM acl_rule WHERE (resource_type = 'all' AND resource_id = '0') AND action = 'all' AND context IN('/',0) AND ((context = '/' OR inheritable = 1)) AND (((entity_type = 'user' AND entity_id IN(1,0)) OR ())) failed. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')))' at line 1
1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')))' at line 1
and this warning appears: Warning: call_user_func_array() expects exactly 2 parameters, 1 given in escher/escher/helpers/hooks/helper.hooks.php on line 32