Default user setting strategy in Zend Framework - zend-framework

I have a site that has different features and functionality based on the location that the user has selected. Each location has events that are unique to that location. These events are the primary reason that a user comes to the site for.
There are key areas of the site that are not navigable unless a location is selected for the user. Therefore, the location has to be presumed until the selected location is known -- I plan on using some basic GeoIP lookups for this.
So the requirements basically boil down to:
Location must be set before any page on the site is loaded
User can change the location setting
The location setting must persist from request to request
This setting should be accessible to the layout and view and will be a prerequisite for most controllers
I can think of a few ways off the top of my head to tackle this (Zend_Registry, custom Zend_Session_Namespace, etc) but I'm curious if there isn't a more widely identified strategy for this type of problem.

I see this as similar to setting language for a site with i18n and so i would implement in a similar fashion. Id probably store the location in a session value, or if the user is registered they could obviously save it to their settings/profile in whatever backend storage mechanism is being used. You could also add this location to the route params as is often done with i18n but that could get messy given its a geo location and not just a locale.

I don't think Zend_Registry might fit your needs, since it will only make location settings available throughout the application during a single request but will not persist.
If you need these settings to be persistent between requests, your best (and very likely - only) choice is Zend_Session.
As to #1, I suggest using a controller plugin for that.

Related

Using a local identifier instead of the box-view identifier - is this possible?

I am wondering whether we can use our own identifier when passing a document towards box-view and then on the basis of this identifier request a view session. This would prevent us from the need to implement an identifier mapping between the box-view id and our own local id's.
Specifying your own id is not currently possible with the View API. You can suggest features by sending an email with a description of your desired feature to view-api-features#box.com. It helps if you also give some background and use cases for the feature (in this case it's pretty obvious, though). I'll go ahead and suggest this one on your behalf.

In RESTful world, how does next allowed action returned back to UI in a workflow based application

We have a workflow based application where a given process move from one state to another state based on User action.Currently our requirement is to have UI displayed its current state and allow user to take next action steps.So my question is does generally server tells UI the next actions that can be taken or the UI should decide based on current action? This application is designed using RESTful webservices.
The server should provide the client the next allowed actions, also known as state transfers, using links. Those links should, at least, contain two pieces of information: URL and relationship. The relationship tells the client the meaning of the state transition, allowing to recognize what it will do. The URL only says where to locate the service.
Typically, a REST web service should be ignorant of client state. It should only provide the ability to retrieve and update data based on a specific url (you may want to read up on REST). If you are following these guidelines, then the UI should drive any logic regarding the state of a workflow or record.
The hypertext returned provides the next "possible" transitions in the form of 'links' to the "resources". The client/user selects the next transition.
REST APIs must be hypertext-driven may be a good read!

Zend Framework Dynamic Routing

I have a website that is purely database driven. I m new to Zend Framwork, and to the concept of routing, though I have been doing a lot of reading. Brain is pretty much a sponge, with some stuff still trying to be comprehended. I am using ZF mainly for the routing, though I plan to implement other aspects of it when I can. For the most part it is a learning process, so there are some things I will want to write myself without the framework.
Here’s how the site should work:
URLs could be anything from “/” - a root index, to
“/contact/ - a root file, to
 “/deposits/” – a sub-directory to
“/deposits/ira/” - a file in the sub directory.
When a user clicks on a link code will need to parse the REQUEST_URI in order to look into the “pages” table of the database. The sole purpose for this is to get the ID of the record matching the REQUEST_URI. That ID is the key to everything for the page, and other tables are then checked to see if there is any data for other aspects of the page that need to be gotten. The immediate need is for the template name. The site will have a few different pages that are used depending on if it is a home page, section landing page, or content of a section. This information is decided upon when a page is saved to the DB.
I want to be able to take this data and then decide how to route it so that it uses the correct template and can collect the rest of the data from that point to complete the page.
Since sections and pages can be created at any time, there must be controllers that can handle what to do based on the returned template data. This pretty much means the controllers and such will need some standardized names that are non-specific to what values passed in the REQUEST_URI.
How would I accomplish this in Zend so that all this happens before the controller is selected, and only having template names to go by for selecting the correct controller?
Thanks,
Cy
If it's truly the case that all your routes (at least for the frontend) are dynamic, then it sounds like you could do this:
On bootstrap, remove all default routes.
In a plugin on routeStartup, grab the REQUEST_URI and query your db. Presumably that record contains enough info for you to figure out the required controller, action, layout, etc.
2.1 Add a single route (matching the REQUEST_URI) mapping to the controller and action.
2.2 Set the layout to be the required layout.
Then during normal dispatch, the route will match, the controller/action will be invoked and you'll have the layout set correctly.
If the request doesn't match any page stored in your db, you'll have to invoke the error controller/action yourself to give a 404 response.
However, if you eventually have some static (that is, non-db-stored) routes in your app (which I imagine must be the case), then you'll want to match against them before you hit the db to search for the requested one. That matching sounds like a pain (though perhaps there is a way to ask the router itself if the requested route matches, just like the standard dispatcher does).
In that case, perhaps an alternative approach would be to add all those (non-db-stored) routes to the router in the standard way at bootstrap, and put all this REQUEST_URI inspection, db-searching, and controller/action/layout handling in the 404 handler. If the requested url matches something in your db, then _forward() (not redirect) to that controller/action and set the layout, as above.
It's probably not the most performant solution- since _forward() triggers another iteration in the dispatch loop - but it seems like it could work.

Connectedness & HATEOAS

It is said that in a well defined RESTful system, the clients only need to know the root URI or few well known URIs and the client shall discover all other links through these initial URIs. I do understand the benefits (decoupled clients) from this approach but the downside for me is that the client needs to discover the links each time it tries access something i.e given the following hierarchy of resources:
/collection1
collection1
|-sub1
|-sub1sub1
|-sub1sub1sub1
|-sub1sub1sub1sub1
|-sub1sub2
|-sub2
|-sub2sub1
|-sub2sub2
|-sub3
|-sub3sub1
|-sub3sub2
If we follow the "Client only need to know the root URI" approach, then a client shall only be aware of the root URI i.e. /collection1 above and the rest of URIs should be discovered by the clients through hypermedia links. I find this cumbersome because each time a client needs to do a GET, say on sub1sub1sub1sub1, should the client first do a GET on /collection1 and the follow link defined in the returned representation and then do several more GETs on sub resources to reach the desired resource? or is my understanding about connectedness completely wrong?
Best regards,
Suresh
You will run into this mismatch when you try and build a REST api that does not match the flow of the user agent that is consuming the API.
Consider when you run a client application, the user is always presented with some initial screen. If you match the content and options on this screen with the root representation then the available links and desired transitions will match nicely. As the user selects options on the screen, you can transition to other representations and the client UI should be updated to reflect the new representation.
If you try and model your REST API as some kind of linked data repository and your client UI as an independent set of transitions then you will find HATEOAS quite painful.
Yes, it's right that the client application should traverse the links, but once it's discovered a resource, there's nothing wrong with keeping a reference to that resource and using it for a longer time than one request. If your client has the possibility of remembering things permanently, it can do so.
consider how a web browser keeps its bookmarks. You probably have maybe ten or a hundred bookmarks in the browser, and you probably found some of these deep in a hierarchy of pages, but the browser dutifully remembers them without requiring remembering the path it took to find them.
A more rich client application could remember the URI of sub1sub1sub1sub1 and reuse it if it still works. It's likely that it still represents the same thing (it ought to). If it no longer exists or fails for any other client reason (4xx) you could retrace your steps to see if you can find a suitable replacement.
And of course what Darrel Miller said :-)
I don't think that that's the strict requirement. From how I understand it, it is legal for a client to access resources directly and start from there. The important thing is that you do not do this for state transitions, i.e. do not automatically proceed with /foo2 after operating on /foo1 and so forth. Retrieving /products/1234 initially to edit it seems perfectly fine. The server could always return, say, a redirect to /shop/products/1234 to remain backwards compatible (which is desirable for search engines, bookmarks and external links as well).

Making Catalyst calls from the model?

I'm using Catalyst with Catalyst::Plugin::Authentication and
Catalyst::Plugin::Authorization::Roles and am wondering if there is a better
approach to adding an attribute to a model that I'm not seeing.
Each user is permitted to access one or more companies, but there is
always one primary (current) company at a time. The permitted list is
stored in the database, and database access is primarily through DBIC.
My first inclination is to say that it's the user that has a current
company, and thus put it as part of the user model: give the user
package a "sub company { … }" to get/set the user's current company. The
database check is fairly easy; just use "$self->search_related" (a DBIC
method, inherited by the user model).
The problems I run in to are:
The current company needs to persist between requests, but I'd rather
not store it to the database (it should only persist for this
session). The natural place is the session…
There is a role, akin to Unix's root, that allows you to act as
any company, ignoring the list in the database. Checking this role
can be done through the database, but everywhere else in the app uses
$c->assert_user_role and friends.
I've heard its best to keep the models as Catalyst-independent as
possible. It also seems pretty weird to have a model manipulating
$c->session.
Of course, I could move those checks to the controllers, and have the
model accept whatever the controller sends, but that's violating DRY
pretty heavily, and just begging for a security issue if I forget one of
the checks somewhere.
Any suggestions? Or do I just shrug and go ahead and do it in the model?
Thanks, and apologies for the title, I couldn't come up with a good one.
The key is to create an instance of the model class for each request, and then pass in the parts of the request you need. In this case, you probably want to pass in a base resultset. Your model will make all the database calls via $self->resultset->..., and it will "just work" for the current user. (If the current user is root, then you just pass in $schema->resultset("Foo"). If the current user is someone else, then pass in $schema->resultset("Foo")->stuff_that_can_be_seen_by($c->user). Your model then no longer cares.)
I have some slides about this, but they are very outdated:
http://www.jrock.us/doqueue-grr/slide95c.html#end
(See the stuff immediately before and after, also.)
Note that restricted resultsets and web ACLs are orthogonal. You want to make the model as tight as possible (so that your app can't accidentally do something you don't want it to, even if the code says to), but various web-only details will still need to be encoded in ACLs. ("You are not allowed to view this page." is different from "You can only delete your own objects, not everyone's". The ACL handles the first case, the restricted resultset handles the second. Even if you write $rs->delete, since the resultset is restricted, you didn't delete everything in the database. You only deleted the things that you have permission to delete. Convenient!)