I've been struggling with this problem the last 2 hours. I'm trying to add a regex-route to my Zend Framework (V1) application. My other routes are static and stored in my application.ini file and that is where i want to put some new regex-routes.
Before i continue to work on more complex regex routes i started to translate the following (working) route to a regex route:
resources.router.routes.shift-display.route = /shift/display/:id
resources.router.routes.shift-display.defaults.module = shift
resources.router.routes.shift-display.defaults.controller = index
resources.router.routes.shift-display.defaults.action = display
Here is what i came up with:
resources.router.routes.shift-display.type = "Zend_Controller_Router_Route_Regex"
resources.router.routes.shift-display.regex = "shift/display/(\d+)"
resources.router.routes.shift-display.defaults.module = shift
resources.router.routes.shift-display.defaults.controller = index
resources.router.routes.shift-display.defaults.action = display
resources.router.routes.shift-display.map.1 = id
resources.router.routes.shift-display.reverse = "shift/display/%d"
But it's not working. It seems the route isn't recognized by the router. When trying to open e.g. vh.localhost/shift/display/7 i get "Invalid controller specified (display)" so the router uses the default route. I also tried to prepend the regex-route with a slash. I tried to use the url-helper to generate links (with passed ID param) using the new regex-route and it works.
Anyone has a clue?
Sometimes is it just that simple. When definining the route, the mistake was made in that line:
resources.router.routes.shift-display.regex = "shift/display/(\d+)"
It has to be
resources.router.routes.shift-display.route = "shift/display/(\d+)"
4 hours for nothing. But at least I finally found it ;-)
Related
I am reviewing the configuration of FW/1. I notice that some of the routes start with a / and others don't. Is there any difference between the two?
variables.framework.routes = [
{ "chart/home" = "chart/home"},
...
{ "/location/home" = "location/home"},
Have you noticed any difference in behavior from the two? I don't think there is a difference. From the documentation and examples that I could find they are all preceded by a /. I presume that FW/1 is allowing both but they work the same.
Snippet from the documentation here - http://framework-one.github.io/documentation/developing-applications.html#url-routes:
URL Routes
In addition to the standard /section/item and /module:section/item URLs that FW/1 supports ...
An example from farther down that page shows the standard routes starting with a /:
Here’s an example showing all the features together:
variables.framework.routes = [
{ "/product/:id" = "/product/view/id/:id", "/user/{id:[0-9]+}" = "/user/view/id/:id",
hint = "Display a specific product or user" },
{ "/products" = "/product/list", "/users" = "/user/list" },
{ "/old/url" = "302:/new/url" }
];
Here is a link to the code that processes the routes you define - https://github.com/framework-one/fw1/blob/develop/framework/one.cfc#L1954-L2047
In order to test this theory you could try the following.
Browse to www.yourdomain.com/location/home that should match the second route in your example.
Browse to www.yourdomain.com/chart/home that should match the first route in your example.
Browse to www.yourdomain.com/sometextchart/home does that match the first route in your example?
Browse to www.yourdomain.com/somefolder/chart/home does that match the first route in your example?
Browse to www.yourdomain.com/somefolder/sometextchart/home does that match the first route in your example?
I am trying to use the wildcard match on routes in FW/1 v 3.5.
Application.cfc
component extends="framework.one" {
this.name= "Wildcard7";
variables.framework = {
home = 'main.home',
action = 'fuseaction',
baseURL = 'useCgiScriptName',
trace = isDebugMode()
};
variables.framework.routes = [
{ "main/home" = "main/home"},
{ "*" = "main/404"}
];
}
When I run the page, without specifying an action, I get the main/404 page instead of main/home
** FW/1 trace**
How can I get main/404 to run only on invalid pages?
When I run the page, without specifying an action, I get the main/404 page instead of main/home
I assume you are trying to access the page like so - your.domain/index.cfm/main. Note the lack of the home action.
Based on your routes, your first route is saying if the path supplied equals "main/home" then point to the view main/home. If there is an action of home in a main.cfc controller then that will be ran prior to rendering the view.
Leaving off the action, home, would not match any of your current routes; resulting in your wildcard catching it. You would need to handle it by including another route like {"main" = "main"}.
UPDATE:
To access main/home from your.domain/index.cfm, you can try passing a route of {"/" = "main/home"}. I would suggest this being above your wildcard and below any other routes to avoid any freak matches.
I am making a web scraper for a website where I have to download images. I am currently using WWW::Mechanize and doing:
my #images=$mech->find_all_images(url_regex => qr/smallThumb/i);
which gives me all the images that have smallThumb in the URL.
How can I change smallThumb to zoom while retaining the previous links that have smallThumb?
You can do this:
my #smallthumbs = $mech->find_all_images(url_regex => qr/smallThumb/i);
my #zooms = $mech->find_all_images(url_regex => qr/zoom/i);
my #allimages = (#smallthumbs, #zooms);
The risk here is that you could have a URL that fits in both categories and get a dupe.
You can also go monkeying with the regex.
my #smallthumbs_or_zooms = $mech->find_all_images( url_regex => qr/smallThumb|zoom/i );
Consider the configuration below:
#URLMapping(id = "programaManter", parentId = "homeTreinamento", pattern = "/programa/#{id : programaManter.id}", viewId = "/pages/treinamento/ProgramaManter.xhtml")
Lets say that I need to navigate to /programa/1. I've tried the following:
return "/pages/treinamento/ProgramaManter.xhtml?faces-redirect=true&id=" + id;
But instead of navigating to /programa/1 it's navigating to /programa/?id=1, how can I force it to build the url using path parameter instead of query parameter?
Solution posted here on the OCPsoft support forums: http://ocpsoft.org/support/topic/navigation-using-path-parameter-on-pretty-faces-2-0-8-final/#post-25822
Is there any way to parametise the Datasource for the 'source' field in the Template Builder?
We have a multisite setup. As part of this it would save a lot of time and irritation if we could point our Droptrees and Treelists point at the appropriate locations rather than common parents.
For instance:
Content
--Site1
--Data
--Site2
--Data
Instead of having to point our site at the root Content folder I want to point it at the individual data folders, so I want to do something like:
DataSource=/sitecore/content/$sitename/Data
I can't find any articles on this. Is it something that's possible?
Not by default, but you can use this technique to code your datasources:
http://newguid.net/sitecore/2013/coded-field-datasources-in-sitecore/
You could possibly use relative paths if it fits with the rest of your site structure. It could be as simple as:
./Data
But if the fields are on random items all over the tree, that might not be helpul.
Otherwise try looking at:
How to use sitecore query in datasource location? (dynamic datasouce)
You might want to look at using a Querable Datasource Location and plugging into the getRenderingDatasource pipeline.
It's really going to depend on your use cases. The thing I like about this solution is there is no need to create a whole bunch of controls which effectively do he same thing as the default Sitecore ones, and you don't have to individually code up each datasource you require - just set the query you need to get the data. You can also just set the datasource query in the __standard values for the templates.
This is very similar to Holger's suggestion, I just think this code is neater :)
Since Sitecore 7 requires VS 2012 and our company isn't going to upgrade any time soon I was forced to find a Sitecore 6 solution to this.
Drawing on this article and this one I came up with this solution.
public class SCWTreeList : TreeList
{
protected override void OnLoad(EventArgs e)
{
if (!String.IsNullOrEmpty(Source))
this.Source = SourceQuery.Resolve(SContext.ContentDatabase.Items[ItemID], Source);
base.OnLoad(e);
}
}
This creates a custom TreeList control and passes it's Source field through to a class to handle it. All that class needs to do is resolve anything you have in the Source field into a sitecore query path which can then be reassigned to the source field. This will then go on to be handled by Sitecore's own query engine.
So for our multi-site solution it enabled paths such as this:
{A588F1CE-3BB7-46FA-AFF1-3918E8925E09}/$sitename
To resolve to paths such as this:
/sitecore/medialibrary/Product Images/Site2
Our controls will then only show items for the correct site.
This is the method that handles resolving the GUIDs and tokens:
public static string Resolve(Item item, string query)
{
// Resolve tokens
if (query.Contains("$"))
{
MatchCollection matches = Regex.Matches(query, "\\$[a-z]+");
foreach (Match match in matches)
query = query.Replace(match.Value, ResolveToken(item, match.Value));
}
// Resolve GUIDs.
MatchCollection guidMatches = Regex.Matches(query, "^{[a-zA-Z0-9-]+}");
foreach (Match match in guidMatches)
{
Guid guid = Guid.Parse(match.Value);
Item queryItem = SContext.ContentDatabase.GetItem(new ID(guid));
if (item != null)
query = query.Replace(match.Value, queryItem.Paths.FullPath);
}
return query;
}
Token handling below, as you can see it requires that any item using the $siteref token is inside an Site Folder item that we created. That allows us to use a field which contains the name that all of our multi-site content folders must follow - Site Reference. As long at that naming convention is obeyed it allows us to reference folders within the media library or any other shared content within Sitecore.
static string ResolveToken(Item root, string token)
{
switch (token)
{
case "$siteref":
string sRef = string.Empty;
Item siteFolder = root.Axes.GetAncestors().First(x => x.TemplateID.Guid == TemplateKeys.CMS.SiteFolder);
if (siteFolder != null)
sRef = siteFolder.Fields["Site Reference"].Value;
return sRef;
}
throw new Exception("Token '" + token + "' is not recognised. Please disable wishful thinking and try again.");
}
So far this works for TreeLists, DropTrees and DropLists. It would be nice to get it working with DropLinks but this method does not seem to work.
This feels like scratching the surface, I'm sure there's a lot more you could do with this approach.