1 /**
2 * Copyright © Webd 2018
3 * License: MIT (https://github.com/DiamondMVC/Webd/blob/master/LICENSE)
4 * Author: Jacob Jensen (bausshf)
5 */
6 module webd.web.tagcollection;
7 
8 import std.variant : Variant;
9 
10 import webd.web.loop;
11 
12 /// Wrapper around a tag collection.
13 class TagCollection(string tagName = "tags")
14 {
15   private
16   /// The tags of the collection.
17   Variant[string] _values;
18   /// An inner collection of tags.
19   TagCollection!tagName _tags;
20 
21   public:
22   @property
23   {
24     /// Gets the keys of the tags.
25     auto keys() { return _values.keys; }
26   }
27 
28   /**
29   * Adds a tag to the collection.
30   * Params:
31   *   key =   The key of the tag.
32   *   value = The value of the tag.
33   */
34   void add(T = string)(string key, T value)
35   {
36     _values[key] = value;
37   }
38 
39   /**
40   * Removes a tag from the collection.
41   * Params:
42   *   key =   The key of the tag.
43   */
44   void remove(string key)
45   {
46     if (_values)
47     {
48       _values.remove(key);
49     }
50   }
51 
52   /**
53   * Checks whether a key exist in the collection or not.
54   * Params:
55   *   key = The key to check for existence.
56   * Returns:
57   *   Returns true if the key exist, false otherwise.
58   */
59   bool has(string key)
60   {
61     return _values && key in _values;
62   }
63 
64   /**
65   * Gets the value of a tag in the collection.
66   * Params:
67   *   name =         The name of the tag.
68   *   defaultValue = The default value to return if the tag doesn't exist.
69   * Returns:
70   *   The value of the tag, else the default value.
71   */
72   T get(T = string)(string name, lazy T defaultValue = T.init)
73   {
74     if (!_values)
75     {
76       return defaultValue;
77     }
78 
79     import std.variant : Variant;
80     Variant value = _values.get(name, Variant.init);
81 
82     if (!value.hasValue)
83     {
84       return defaultValue;
85     }
86 
87     return value.get!T;
88   }
89 
90   /*
91   * Gets a loop from the collection.
92   * Params:
93   *   name = The name of the loop.
94   * Returns:
95   *   The loop if existing, else an empty loop range.
96   */
97   Loop getLoop(string name)
98   {
99     return get!Loop(name);
100   }
101 
102   /// Clears all tags.
103   void clearTags()
104   {
105     if (_values)
106     {
107       _values.clear();
108     }
109   }
110 
111   /**
112   * Clears tags based on a tag prefix ex. "page::", "item::" etc.
113   * Params:
114   *   tagPrefix = The tag prefix.
115   */
116   void clearTags(string tagPrefix)
117   {
118     import std.algorithm : startsWith;
119 
120     string[] keysToRemove;
121 
122     foreach (key; keys)
123     {
124       if (key.startsWith(tagPrefix))
125       {
126         keysToRemove ~= key;
127       }
128     }
129 
130     foreach (keyToRemove; keysToRemove)
131     {
132       _values.remove(keyToRemove);
133     }
134   }
135 
136   /// Creates an inner tag collection.
137   void createTags()
138   {
139     _tags = new TagCollection!tagName;
140   }
141 
142   @property
143   {
144     /// Gets the inner tag collection.
145     mixin("TagCollection " ~ tagName  ~ "() { return _tags; }");
146   }
147 }