ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

381 lines
13 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
  4. //
  5. // See accompanying file COPYING.TXT file for licensing details.
  6. //
  7. ///////////////////////////////////////////////////////////////////////////////
  8. #ifndef CPPCMS_URL_MAPPER_H
  9. #define CPPCMS_URL_MAPPER_H
  10. #include <cppcms/defs.h>
  11. #include <cppcms/string_key.h>
  12. #include <booster/noncopyable.h>
  13. #include <booster/hold_ptr.h>
  14. #include <cppcms/filters.h>
  15. #include <string>
  16. #include <vector>
  17. namespace cppcms {
  18. class application;
  19. ///
  20. /// \brief class for mapping URLs - the opposite of dispatch
  21. ///
  22. /// This class is useful for mapping between different page identifications
  23. /// that represent different classes/view and the URL.
  24. ///
  25. ///
  26. /// The URL mapping is done in hierarchy of applications where each application
  27. /// has its own name and they bundler into single hierarchy. Each application in hierarchy
  28. /// can be referred by its key and location. It may have different "urls" for mapping
  29. /// different values.
  30. ///
  31. /// For example, we develop a content management system with following tools:
  32. ///
  33. /// - site
  34. /// - news
  35. /// - article
  36. /// - category
  37. /// - forums
  38. /// - topics
  39. /// - threads
  40. /// - users
  41. /// - management
  42. /// - registration
  43. /// - profile
  44. ///
  45. /// Each node above is represented my cppcms::application and its children mounted
  46. /// to it. In order to access each URL we use "file system" like convention:
  47. ///
  48. /// - "/" - the default site page
  49. /// - "/news" - the default news page
  50. /// - "/news/article" - the default article page
  51. /// - "/news/category/by_date" - the categories pages sorted by data
  52. /// - "/news/category/by_interest" - the categories pages sorted by interest
  53. /// - "/news/category" - the default category pages
  54. ///
  55. /// And so on.
  56. ///
  57. /// Each application can be referred by its full path from root or by its relative path,
  58. /// so if we for example in article sub-application and we want to refer to "category"
  59. /// URL we would use something like map(out(),"../category/by_interest",category_id);
  60. ///
  61. /// In order to all this process work, each application should mount its children by some name,
  62. /// like:
  63. ///
  64. /// \code
  65. /// site::site(cppcms::service &s) :
  66. /// cppcms::application(s),
  67. /// news_(s),
  68. /// forums_(s),
  69. /// users_(s)
  70. /// {
  71. /// add(news_);
  72. /// mapper().mount("news","/news{1}",news_);
  73. /// add(forums_);
  74. /// mapper().mount("forums","/forums{1}",forums_);
  75. /// ...
  76. /// \endcode
  77. ///
  78. /// You can also use cppcms::application::add and cppcms::application::attach that allows
  79. /// to provide mapping for url_dispatcher and url_mapper in a single command like:
  80. ///
  81. /// \code
  82. /// add(news_,
  83. /// "news","/news{1}",
  84. /// "/news((/.*)?)",1);
  85. /// \endcode
  86. ///
  87. /// Which effectively the same as:
  88. ///
  89. /// \code
  90. /// add(news_);
  91. /// mapper().mount("news","/news{1}",news_);
  92. /// dispatcher().mount("/news((/.*)?)",news_,1);
  93. /// \endcode
  94. ///
  95. /// Such system allows using "url" tag in templates system easily as"
  96. ///
  97. /// \code
  98. /// <a href="<% url "/news/article" using article id %>" >...</a>
  99. /// \endcode
  100. ///
  101. /// Each mounted application may a default URL (something like index.html)
  102. /// which is mapped when mounted application is referred. So for example there
  103. /// are may be following URLs:
  104. ///
  105. /// - "/news/article" or "/news/article/" - the default URL
  106. /// - "/news/article/preview" - preview unpublished article URL.
  107. ///
  108. /// They can be defined in article class as following:
  109. ///
  110. /// \code
  111. /// article::article(cppcms::service &s) : cppcms::application(s)
  112. /// {
  113. /// mapper().assign("/{1}"); // the default URL
  114. /// dispatcher().assign("/(\\d+)",&article::display,this,1);
  115. /// mapper().assign("preview","/{1}/preview"); // the preview URL
  116. /// dispatcher().assign("/(\\d+)/preview",&article::preview,this,1);
  117. /// }
  118. /// \endcode
  119. ///
  120. /// Additional supported feature is "named" parameters which are usually set to
  121. /// some default value using set_value, they are defined by special keywords between
  122. /// instead of numbers.
  123. ///
  124. /// For example assign("article", "/article/{lang}/{1}") were "lang" is special value for language
  125. /// defined by set_value("lang","en"), so mapping map(out(),"article",10) would create
  126. /// a URL "/article/en/10"
  127. ///
  128. /// Sometimes it is useful to change such values there are two ways to do it:
  129. ///
  130. /// - Overloading keyword with different parameters number assign("article","/article/{1}/{2}")
  131. /// and then calling map(out(),"article","ru",10) for URL like "/article/ru/10".
  132. /// - Using naming of parameters at mapping level by prepending comma separated keywords at the
  133. /// end of the path line after ";" map(out(),"article;lang","ru",10) - which would effectively work
  134. /// like temporary calling set_value("lang","ru") and then calling map(out(),"article",10).
  135. /// Unlike the previous case it also allows to do such changes globally.
  136. /// <br>
  137. /// For example if "news" application mounts article using "/{lang}/{1}" then
  138. /// using such mapping would affect top level URL that does not belong to specific application.
  139. ///
  140. ///
  141. ///
  142. ///
  143. ///
  144. ///
  145. class CPPCMS_API url_mapper : public booster::noncopyable {
  146. public:
  147. /// \cond INTERNAL
  148. url_mapper(application *app);
  149. ~url_mapper();
  150. /// \endcond
  151. ///
  152. /// Get the root of the application - the string that
  153. /// is added to the any URL patter like "/forum" or
  154. /// "http://my.site.com"
  155. ///
  156. std::string root();
  157. ///
  158. /// Set the root of the application - the string that
  159. /// is added to the any URL patter like "/forum" or
  160. /// "http://my.site.com"
  161. ///
  162. void root(std::string const &r);
  163. ///
  164. /// Provide a mapping between special \a key and a \a url pattern.
  165. ///
  166. /// URL patter is a string that includes mapped patters between "{" and "}"
  167. /// brackets. For example "/page/{1}" where "{1}" is being substituted
  168. /// by the first parameter in map functions.
  169. ///
  170. /// The ids can be numbers - 1 to 6 and special keys that can be changed
  171. /// in the run time using set_value functions. For example:
  172. ///
  173. /// "/wiki/{lang}/page/{1}"
  174. ///
  175. /// Where "lang" can be defined by "set_value". For example.
  176. ///
  177. /// For the url above with "lang" set to "en" and first parameter "cppcms"
  178. /// the string would be "/wiki/en/page/cppcms"
  179. ///
  180. /// Note the keys may be overloaded by number of parameters as for example:
  181. ///
  182. /// - <tt>assign("page","/wiki/{1}/page/{2}");</tt>
  183. /// - <tt>assign("page","/wiki/{lang}/page/{1}");</tt>
  184. /// - <tt>assign("page","/wiki/{lang}/page/main");</tt>
  185. ///
  186. /// Then map(output,"page") - would create "/wiki/en/page/main",
  187. /// map(output,"page",134) would create "/wiki/en/page/132" and
  188. /// map(output,"page","ru","cppcms") would create "/wiki/ru/page/cppcms"
  189. ///
  190. /// Note: They keys containing "/", "," or ";" and keys with values "..", ".", "" are prohibited
  191. /// as they have special meanings
  192. ///
  193. void assign(std::string const &key,std::string const &url);
  194. ///
  195. /// Map the default key for the application, \a url has same rules as for assign(key,url) but
  196. /// they rather refer to default application's URL when it is used in hierarchy.
  197. ///
  198. void assign(std::string const &url);
  199. ///
  200. /// Set special value for a key that would be used
  201. /// in URL mapping, for example set_value("lang","en")
  202. ///
  203. /// Note: this value is defined globally for all applications hierarchy and not only
  204. /// for this specific application
  205. ///
  206. void set_value(std::string const &key,std::string const &value);
  207. ///
  208. /// Clear the special value - reset to empty
  209. ///
  210. /// Note: this value is cleared globally for all applications hierarchy and not only
  211. /// for this specific application
  212. ///
  213. void clear_value(std::string const &key);
  214. ///
  215. /// Write the URL to output stream \a out for the URL \a path with 0 parameters
  216. ///
  217. void map( std::ostream &out,
  218. char const *path);
  219. ///
  220. /// Write the URL to output stream \a out for the URL \a path with 1 parameters
  221. ///
  222. void map( std::ostream &out,
  223. char const *path,
  224. filters::streamable const &p1);
  225. ///
  226. /// Write the URL to output stream \a out for the URL \a path with 2 parameters
  227. ///
  228. void map( std::ostream &out,
  229. char const *path,
  230. filters::streamable const &p1,
  231. filters::streamable const &p2);
  232. ///
  233. /// Write the URL to output stream \a out for the URL \a path with 3 parameters
  234. ///
  235. void map( std::ostream &out,
  236. char const *path,
  237. filters::streamable const &p1,
  238. filters::streamable const &p2,
  239. filters::streamable const &p3);
  240. ///
  241. /// Write the URL to output stream \a out for the URL \a path with 4 parameters
  242. ///
  243. void map( std::ostream &out,
  244. char const *path,
  245. filters::streamable const &p1,
  246. filters::streamable const &p2,
  247. filters::streamable const &p3,
  248. filters::streamable const &p4);
  249. ///
  250. /// Write the URL to output stream \a out for the URL \a path with 5 parameters
  251. ///
  252. void map( std::ostream &out,
  253. char const *path,
  254. filters::streamable const &p1,
  255. filters::streamable const &p2,
  256. filters::streamable const &p3,
  257. filters::streamable const &p4,
  258. filters::streamable const &p5);
  259. ///
  260. /// Write the URL to output stream \a out for the URL \a path with 6 parameters
  261. ///
  262. void map( std::ostream &out,
  263. char const *path,
  264. filters::streamable const &p1,
  265. filters::streamable const &p2,
  266. filters::streamable const &p3,
  267. filters::streamable const &p4,
  268. filters::streamable const &p5,
  269. filters::streamable const &p6);
  270. ///
  271. /// Write the URL to output stream \a out for the URL \a path with 0 parameters
  272. ///
  273. void map( std::ostream &out,
  274. std::string const &path);
  275. ///
  276. /// Write the URL to output stream \a out for the URL \a path with 1 parameters
  277. ///
  278. void map( std::ostream &out,
  279. std::string const &path,
  280. filters::streamable const &p1);
  281. ///
  282. /// Write the URL to output stream \a out for the URL \a path with 2 parameters
  283. ///
  284. void map( std::ostream &out,
  285. std::string const &path,
  286. filters::streamable const &p1,
  287. filters::streamable const &p2);
  288. ///
  289. /// Write the URL to output stream \a out for the URL \a path with 3 parameters
  290. ///
  291. void map( std::ostream &out,
  292. std::string const &path,
  293. filters::streamable const &p1,
  294. filters::streamable const &p2,
  295. filters::streamable const &p3);
  296. ///
  297. /// Write the URL to output stream \a out for the URL \a path with 4 parameters
  298. ///
  299. void map( std::ostream &out,
  300. std::string const &path,
  301. filters::streamable const &p1,
  302. filters::streamable const &p2,
  303. filters::streamable const &p3,
  304. filters::streamable const &p4);
  305. ///
  306. /// Write the URL to output stream \a out for the URL \a path with 5 parameters
  307. ///
  308. void map( std::ostream &out,
  309. std::string const &path,
  310. filters::streamable const &p1,
  311. filters::streamable const &p2,
  312. filters::streamable const &p3,
  313. filters::streamable const &p4,
  314. filters::streamable const &p5);
  315. ///
  316. /// Write the URL to output stream \a out for the URL \a path with 6 parameters
  317. ///
  318. void map( std::ostream &out,
  319. std::string const &path,
  320. filters::streamable const &p1,
  321. filters::streamable const &p2,
  322. filters::streamable const &p3,
  323. filters::streamable const &p4,
  324. filters::streamable const &p5,
  325. filters::streamable const &p6);
  326. ///
  327. /// Mount sub application \a app using name \a name to \a url.
  328. ///
  329. /// The URL format as in assign but it requires a single parameter {1}
  330. /// which would be substituted with the mapping of the URL of sub-application
  331. /// instead of using "root" patch
  332. ///
  333. void mount(std::string const &name,std::string const &url,application &app);
  334. ///
  335. /// Get a mapper of mounted application by its name
  336. ///
  337. url_mapper &child(std::string const &name);
  338. ///
  339. /// Get a parent mapper, if not exists throws cppcms_error
  340. ///
  341. url_mapper &parent();
  342. ///
  343. /// Get a topmost mapper, if have no parents returns reference to \c this.
  344. ///
  345. url_mapper &topmost();
  346. private:
  347. void real_assign(std::string const &key,std::string const &url,application *child = 0);
  348. url_mapper &get_mapper_for_key(string_key const &key,string_key &real_key,std::vector<string_key> &direct);
  349. url_mapper *root_mapper();
  350. void real_map( char const *key,
  351. filters::streamable const *const *params,
  352. size_t params_no,
  353. std::ostream &output);
  354. struct data;
  355. booster::hold_ptr<data> d;
  356. };
  357. };
  358. #endif