Posts 2 Posts - Version 1.6.4

Version Description

  • added Danish translation. props phh
  • updated Swedish translation. props EyesX
  • fixed issue with multiple parse_query calls. props hezachenary
  • added p2p_post_admin_column_link and p2p_user_admin_column_link filters. props PareshRadadiya
Download this release

Release Info

Developer scribu
Plugin Icon wp plugin Posts 2 Posts
Version 1.6.4
Comparing to
See all releases

Code changes from version 1.6.3 to 1.6.4

Files changed (100) hide show
  1. CONTRIBUTING.md +14 -10
  2. admin/box.js +55 -3
  3. admin/column-post.php +3 -1
  4. admin/column-user.php +3 -1
  5. admin/mustache.php +7 -12
  6. composer.json +18 -0
  7. core/init.php +0 -18
  8. lang/posts-to-posts-da_DK.mo +0 -0
  9. lang/posts-to-posts-da_DK.po +156 -0
  10. lang/posts-to-posts-sv_SE.mo +0 -0
  11. lang/posts-to-posts-sv_SE.po +130 -55
  12. lang/posts-to-posts-zh_CN.mo +0 -0
  13. lang/posts-to-posts-zh_CN.po +155 -0
  14. mustache/LICENSE +0 -22
  15. mustache/Mustache.php +0 -910
  16. mustache/MustacheLoader.php +0 -85
  17. mustache/README.markdown +0 -98
  18. posts-to-posts.php +26 -9
  19. readme.txt +8 -2
  20. vendor/mustache/mustache/.travis.yml +12 -0
  21. vendor/mustache/mustache/CONTRIBUTING.md +33 -0
  22. vendor/mustache/mustache/LICENSE +21 -0
  23. vendor/mustache/mustache/README.md +71 -0
  24. vendor/mustache/mustache/composer.json +24 -0
  25. vendor/mustache/mustache/phpunit.xml.dist +17 -0
  26. vendor/mustache/mustache/src/Mustache/Autoloader.php +74 -0
  27. vendor/mustache/mustache/src/Mustache/Cache.php +38 -0
  28. vendor/mustache/mustache/src/Mustache/Cache/AbstractCache.php +60 -0
  29. vendor/mustache/mustache/src/Mustache/Cache/FilesystemCache.php +159 -0
  30. vendor/mustache/mustache/src/Mustache/Cache/NoopCache.php +49 -0
  31. vendor/mustache/mustache/src/Mustache/Compiler.php +493 -0
  32. vendor/mustache/mustache/src/Mustache/Context.php +154 -0
  33. vendor/mustache/mustache/src/Mustache/Engine.php +747 -0
  34. vendor/mustache/mustache/src/Mustache/Exception.php +18 -0
  35. vendor/mustache/mustache/src/Mustache/Exception/InvalidArgumentException.php +18 -0
  36. vendor/mustache/mustache/src/Mustache/Exception/LogicException.php +18 -0
  37. vendor/mustache/mustache/src/Mustache/Exception/RuntimeException.php +18 -0
  38. vendor/mustache/mustache/src/Mustache/Exception/SyntaxException.php +36 -0
  39. vendor/mustache/mustache/src/Mustache/Exception/UnknownFilterException.php +32 -0
  40. vendor/mustache/mustache/src/Mustache/Exception/UnknownHelperException.php +32 -0
  41. vendor/mustache/mustache/src/Mustache/Exception/UnknownTemplateException.php +32 -0
  42. vendor/mustache/mustache/src/Mustache/HelperCollection.php +172 -0
  43. vendor/mustache/mustache/src/Mustache/LambdaHelper.php +49 -0
  44. vendor/mustache/mustache/src/Mustache/Loader.php +27 -0
  45. vendor/mustache/mustache/src/Mustache/Loader/ArrayLoader.php +79 -0
  46. vendor/mustache/mustache/src/Mustache/Loader/CascadingLoader.php +69 -0
  47. vendor/mustache/mustache/src/Mustache/Loader/FilesystemLoader.php +124 -0
  48. vendor/mustache/mustache/src/Mustache/Loader/InlineLoader.php +123 -0
  49. vendor/mustache/mustache/src/Mustache/Loader/MutableLoader.php +35 -0
  50. vendor/mustache/mustache/src/Mustache/Loader/StringLoader.php +39 -0
  51. vendor/mustache/mustache/src/Mustache/Logger.php +144 -0
  52. vendor/mustache/mustache/src/Mustache/Logger/AbstractLogger.php +121 -0
  53. vendor/mustache/mustache/src/Mustache/Logger/StreamLogger.php +194 -0
  54. vendor/mustache/mustache/src/Mustache/Parser.php +206 -0
  55. vendor/mustache/mustache/src/Mustache/Template.php +176 -0
  56. vendor/mustache/mustache/src/Mustache/Tokenizer.php +327 -0
  57. {core → vendor/scribu/lib-posts-to-posts}/api.php +0 -0
  58. {core → vendor/scribu/lib-posts-to-posts}/autoload.php +6 -0
  59. vendor/scribu/lib-posts-to-posts/composer.json +13 -0
  60. {core → vendor/scribu/lib-posts-to-posts}/connection-type-factory.php +0 -0
  61. {core → vendor/scribu/lib-posts-to-posts}/connection-type.php +0 -0
  62. {core → vendor/scribu/lib-posts-to-posts}/determinate-connection-type.php +0 -0
  63. {core → vendor/scribu/lib-posts-to-posts}/directed-connection-type.php +0 -0
  64. {core → vendor/scribu/lib-posts-to-posts}/direction-strategy.php +0 -0
  65. {core → vendor/scribu/lib-posts-to-posts}/exception.php +0 -0
  66. {core → vendor/scribu/lib-posts-to-posts}/indeterminate-connection-type.php +0 -0
  67. {core → vendor/scribu/lib-posts-to-posts}/indeterminate-directed-connection-type.php +0 -0
  68. {core → vendor/scribu/lib-posts-to-posts}/item-any.php +0 -0
  69. {core → vendor/scribu/lib-posts-to-posts}/item-attachment.php +0 -0
  70. {core → vendor/scribu/lib-posts-to-posts}/item-post.php +0 -0
  71. {core → vendor/scribu/lib-posts-to-posts}/item-user.php +0 -0
  72. {core → vendor/scribu/lib-posts-to-posts}/item.php +0 -0
  73. {core → vendor/scribu/lib-posts-to-posts}/list-renderer.php +0 -0
  74. {core → vendor/scribu/lib-posts-to-posts}/list.php +0 -0
  75. {core → vendor/scribu/lib-posts-to-posts}/query-post.php +0 -0
  76. {core → vendor/scribu/lib-posts-to-posts}/query-user.php +0 -0
  77. {core → vendor/scribu/lib-posts-to-posts}/query.php +2 -2
  78. {core → vendor/scribu/lib-posts-to-posts}/reciprocal-connection-type.php +0 -0
  79. {core → vendor/scribu/lib-posts-to-posts}/shortcodes.php +0 -0
  80. {core → vendor/scribu/lib-posts-to-posts}/side-attachment.php +0 -0
  81. {core → vendor/scribu/lib-posts-to-posts}/side-post.php +0 -0
  82. {core → vendor/scribu/lib-posts-to-posts}/side-user.php +0 -0
  83. {core → vendor/scribu/lib-posts-to-posts}/side.php +0 -0
  84. {core → vendor/scribu/lib-posts-to-posts}/storage.php +0 -0
  85. {core → vendor/scribu/lib-posts-to-posts}/url-query.php +0 -0
  86. {core → vendor/scribu/lib-posts-to-posts}/util.php +0 -0
  87. {core → vendor/scribu/lib-posts-to-posts}/widget.php +0 -0
  88. {scb → vendor/scribu/scb-framework}/AdminPage.php +0 -0
  89. {scb → vendor/scribu/scb-framework}/BoxesPage.php +0 -0
  90. {scb → vendor/scribu/scb-framework}/Cron.php +0 -0
  91. {scb → vendor/scribu/scb-framework}/Forms.php +0 -0
  92. {scb → vendor/scribu/scb-framework}/Hooks.php +0 -0
  93. {scb → vendor/scribu/scb-framework}/Options.php +0 -0
  94. {scb → vendor/scribu/scb-framework}/PostMetabox.php +3 -3
  95. {scb → vendor/scribu/scb-framework}/Table.php +0 -0
  96. {scb → vendor/scribu/scb-framework}/Util.php +2 -0
  97. {scb → vendor/scribu/scb-framework}/Widget.php +0 -0
  98. {scb → vendor/scribu/scb-framework}/composer.json +0 -0
  99. {scb → vendor/scribu/scb-framework}/load-composer.php +0 -0
  100. {scb → vendor/scribu/scb-framework}/load.php +0 -0
CONTRIBUTING.md CHANGED
@@ -2,14 +2,24 @@ This guide is meant for developers wanting to work on the plugin code.
2
 
3
  ### Setup
4
 
5
- Make a fork and clone it:
6
 
7
  ```
8
- git clone --recursive git@github.com:{YOUR GITHUB USERNAME}/wp-posts-to-posts.git posts-to-posts
 
 
 
 
 
 
9
  ```
10
 
11
  You can now work on the PHP and CSS files. Please follow the [WordPress Coding Standards](http://make.wordpress.org/core/handbook/coding-standards/).
12
 
 
 
 
 
13
  ### Unit Tests
14
 
15
  If you want to add a new feature, please consider adding a new test for it as well.
@@ -24,14 +34,8 @@ Step 1: Install and configure the official WordPress testing suite:
24
 
25
  Note that all data in the test DB will be _deleted_ once you run the tests.
26
 
27
- Step 2: Install PHPUnit via [Composer](https://getcomposer.org):
28
-
29
- ```bash
30
- php composer.phar install --dev
31
- ```
32
-
33
- Step 3: Run the tests:
34
 
35
  ```bash
36
- ./vendor/bin/phpunit
37
  ```
2
 
3
  ### Setup
4
 
5
+ Step 1: Make a fork and clone it:
6
 
7
  ```
8
+ git clone git@github.com:{YOUR GITHUB USERNAME}/wp-posts-to-posts.git posts-to-posts
9
+ ```
10
+
11
+ Step 2: Install the dependencies via [Composer](https://getcomposer.org):
12
+
13
+ ```bash
14
+ php composer.phar install
15
  ```
16
 
17
  You can now work on the PHP and CSS files. Please follow the [WordPress Coding Standards](http://make.wordpress.org/core/handbook/coding-standards/).
18
 
19
+ Step 3: Open a pull request.
20
+
21
+ **Note:** This repository only contains the admin UI; the core functionality is in [lib-posts-to-posts](https://github.com/scribu/wp-lib-posts-to-posts).
22
+
23
  ### Unit Tests
24
 
25
  If you want to add a new feature, please consider adding a new test for it as well.
34
 
35
  Note that all data in the test DB will be _deleted_ once you run the tests.
36
 
37
+ Step 2: Run the tests:
 
 
 
 
 
 
38
 
39
  ```bash
40
+ phpunit
41
  ```
admin/box.js CHANGED
@@ -20,11 +20,16 @@
20
  return jQuery('#p2p-template-' + name).html();
21
  };
22
 
 
23
  Candidate = Backbone.Model.extend({});
24
 
 
25
  Connection = Backbone.Model.extend({});
26
 
 
27
  Candidates = Backbone.Model.extend({
 
 
28
  sync: function() {
29
  var params, _this = this;
30
  params = {
@@ -36,6 +41,8 @@
36
  _this.trigger('sync', response);
37
  });
38
  },
 
 
39
  validate: function(attrs) {
40
  var _ref = attrs.paged;
41
  if (0 < _ref && _ref <= this.total_pages) {
@@ -45,8 +52,11 @@
45
  }
46
  });
47
 
 
48
  Connections = Backbone.Collection.extend({
49
  model: Connection,
 
 
50
  createItemAndConnect: function(title) {
51
  var data, _this = this;
52
  data = {
@@ -57,6 +67,8 @@
57
  _this.trigger('create', response);
58
  });
59
  },
 
 
60
  create: function(candidate) {
61
  var data, _this = this;
62
  data = {
@@ -67,6 +79,8 @@
67
  _this.trigger('create', response);
68
  });
69
  },
 
 
70
  "delete": function(connection) {
71
  var data, _this = this;
72
  data = {
@@ -77,6 +91,8 @@
77
  _this.trigger('delete', response, connection);
78
  });
79
  },
 
 
80
  clear: function() {
81
  var data, _this = this;
82
  data = {
@@ -88,17 +104,21 @@
88
  }
89
  });
90
 
 
91
  ConnectionsView = Backbone.View.extend({
 
92
  events: {
93
  'click th.p2p-col-delete .p2p-icon': 'clear',
94
  'click td.p2p-col-delete .p2p-icon': 'delete'
95
  },
 
96
  initialize: function(options) {
97
  this.options = options;
98
  this.maybe_make_sortable();
99
  this.collection.on('create', this.afterCreate, this);
100
  this.collection.on('clear', this.afterClear, this);
101
  },
 
102
  maybe_make_sortable: function() {
103
  if (this.$('th.p2p-col-order').length) {
104
  this.$('tbody').sortable({
@@ -114,6 +134,7 @@
114
  });
115
  }
116
  },
 
117
  clear: function(ev) {
118
  var $td;
119
  ev.preventDefault();
@@ -124,9 +145,11 @@
124
  row_wait($td);
125
  this.collection.clear();
126
  },
 
127
  afterClear: function() {
128
  this.$el.hide().find('tbody').html('');
129
  },
 
130
  "delete": function(ev) {
131
  var $td, req;
132
  ev.preventDefault();
@@ -139,20 +162,25 @@
139
  remove_row($td);
140
  });
141
  },
 
142
  afterCreate: function(response) {
143
  this.$el.show().find('tbody').append(response.row);
144
  this.collection.trigger('append', response);
145
  }
146
  });
147
 
 
148
  CandidatesView = Backbone.View.extend({
 
149
  template: Mustache.compile(get_mustache_template('tab-list')),
 
150
  events: {
151
  'keypress :text': 'handleReturn',
152
  'keyup :text': 'handleSearch',
153
  'click .p2p-prev, .p2p-next': 'changePage',
154
  'click td.p2p-col-create div': 'promote'
155
  },
 
156
  initialize: function(options) {
157
  this.options = options;
158
  this.spinner = options.spinner;
@@ -162,6 +190,7 @@
162
  this.collection.on('error', this.afterInvalid, this);
163
  this.collection.on('invalid', this.afterInvalid, this);
164
  },
 
165
  promote: function(ev) {
166
  var $td, req, _this = this;
167
  ev.preventDefault();
@@ -179,11 +208,13 @@
179
  }
180
  });
181
  },
 
182
  handleReturn: function(ev) {
183
  if (ev.keyCode === ENTER_KEY) {
184
  ev.preventDefault();
185
  }
186
  },
 
187
  handleSearch: function(ev) {
188
  var $searchInput, delayed,
189
  _this = this;
@@ -204,6 +235,7 @@
204
  });
205
  }, 400);
206
  },
 
207
  changePage: function(ev) {
208
  var $navButton, new_page;
209
  $navButton = jQuery(ev.currentTarget);
@@ -216,6 +248,7 @@
216
  this.spinner.appendTo(this.$('.p2p-navigation'));
217
  this.collection.save('paged', new_page);
218
  },
 
219
  afterCandidatesRefreshed: function(response) {
220
  this.spinner.remove();
221
  this.$('button, .p2p-results, .p2p-navigation, .p2p-notice').remove();
@@ -229,22 +262,27 @@
229
  }
230
  });
231
 
 
232
  CreatePostView = Backbone.View.extend({
 
233
  events: {
234
  'click button': 'createItem',
235
  'keypress :text': 'handleReturn'
236
  },
 
237
  initialize: function(options) {
238
  this.options = options;
239
  this.createButton = this.$('button');
240
  this.createInput = this.$(':text');
241
  },
 
242
  handleReturn: function(ev) {
243
  if (ev.keyCode === ENTER_KEY) {
244
  this.createButton.click();
245
  ev.preventDefault();
246
  }
247
  },
 
248
  createItem: function(ev) {
249
  var req, title, _this = this;
250
  ev.preventDefault();
@@ -265,11 +303,14 @@
265
  }
266
  });
267
 
 
268
  MetaboxView = Backbone.View.extend({
 
269
  events: {
270
  'click .p2p-toggle-tabs': 'toggleTabs',
271
  'click .wp-tab-bar li': 'setActiveTab'
272
  },
 
273
  initialize: function(options) {
274
  this.options = options;
275
  this.spinner = options.spinner;
@@ -278,6 +319,7 @@
278
  options.connections.on('clear', this.afterConnectionDeleted, this);
279
  options.connections.on('delete', this.afterConnectionDeleted, this);
280
  },
 
281
  toggleTabs: function(ev) {
282
  var $tabs;
283
  ev.preventDefault();
@@ -288,6 +330,7 @@
288
  this.initializedCandidates = true;
289
  }
290
  },
 
291
  setActiveTab: function(ev) {
292
  var $tab;
293
  ev.preventDefault();
@@ -296,11 +339,13 @@
296
  $tab.addClass('wp-tab-active');
297
  this.$el.find('.tabs-panel').hide().end().find($tab.data('ref')).show().find(':text').focus();
298
  },
 
299
  afterConnectionAppended: function(response) {
300
  if ('one' === this.options.cardinality) {
301
  this.$('.p2p-create-connections').hide();
302
  }
303
  },
 
304
  afterConnectionDeleted: function(response) {
305
  if ('one' === this.options.cardinality) {
306
  this.$('.p2p-create-connections').show();
@@ -315,9 +360,9 @@
315
  };
316
 
317
  jQuery(function() {
318
- var clearVal, setVal;
319
  if (!jQuery('<input placeholder="1" />')[0].placeholder) {
320
- setVal = function() {
321
  var $this;
322
  $this = jQuery(this);
323
  if (!$this.val()) {
@@ -325,7 +370,8 @@
325
  $this.addClass('p2p-placeholder');
326
  }
327
  };
328
- clearVal = function() {
 
329
  var $this;
330
  $this = jQuery(this);
331
  if ($this.hasClass('p2p-placeholder')) {
@@ -340,22 +386,27 @@
340
 
341
  jQuery('.p2p-box').each(function() {
342
  var $metabox, $spinner, candidates, candidatesView, connections, connectionsView, createPostView, ctype, metaboxView;
 
343
  $metabox = jQuery(this);
 
344
  $spinner = jQuery('<img>', {
345
  'src': P2PAdminL10n.spinner,
346
  'class': 'p2p-spinner'
347
  });
 
348
  candidates = new Candidates({
349
  's': '',
350
  'paged': 1
351
  });
352
  candidates.total_pages = $metabox.find('.p2p-total').data('num') || 1;
 
353
  ctype = {
354
  p2p_type: $metabox.data('p2p_type'),
355
  direction: $metabox.data('direction'),
356
  from: jQuery('#post_ID').val()
357
  };
358
 
 
359
  function ajax_request(options, callback) {
360
  var params = _.extend({}, options, candidates.attributes, ctype, {
361
  action: 'p2p_box',
@@ -385,6 +436,7 @@
385
 
386
  connections = new Connections();
387
  connections.ajax_request = ajax_request;
 
388
  connectionsView = new ConnectionsView({
389
  el: $metabox.find('.p2p-connections'),
390
  collection: connections,
20
  return jQuery('#p2p-template-' + name).html();
21
  };
22
 
23
+ // Class for representing a single connection candidate
24
  Candidate = Backbone.Model.extend({});
25
 
26
+ // Class for representing a single connection
27
  Connection = Backbone.Model.extend({});
28
 
29
+ // Class for holding search parameters; not really a model
30
  Candidates = Backbone.Model.extend({
31
+
32
+ // (Re)perform a search with the current parameters
33
  sync: function() {
34
  var params, _this = this;
35
  params = {
41
  _this.trigger('sync', response);
42
  });
43
  },
44
+
45
+ // Validation function, called by Backbone when parameters are changed
46
  validate: function(attrs) {
47
  var _ref = attrs.paged;
48
  if (0 < _ref && _ref <= this.total_pages) {
52
  }
53
  });
54
 
55
+ // Class for holding a list of connections
56
  Connections = Backbone.Collection.extend({
57
  model: Connection,
58
+
59
+ // Create both a candidate item and a connection
60
  createItemAndConnect: function(title) {
61
  var data, _this = this;
62
  data = {
67
  _this.trigger('create', response);
68
  });
69
  },
70
+
71
+ // Create a connection from a candidate
72
  create: function(candidate) {
73
  var data, _this = this;
74
  data = {
79
  _this.trigger('create', response);
80
  });
81
  },
82
+
83
+ // Delete a connection
84
  "delete": function(connection) {
85
  var data, _this = this;
86
  data = {
91
  _this.trigger('delete', response, connection);
92
  });
93
  },
94
+
95
+ // Delete all connections
96
  clear: function() {
97
  var data, _this = this;
98
  data = {
104
  }
105
  });
106
 
107
+ // View responsible for the connection list
108
  ConnectionsView = Backbone.View.extend({
109
+
110
  events: {
111
  'click th.p2p-col-delete .p2p-icon': 'clear',
112
  'click td.p2p-col-delete .p2p-icon': 'delete'
113
  },
114
+
115
  initialize: function(options) {
116
  this.options = options;
117
  this.maybe_make_sortable();
118
  this.collection.on('create', this.afterCreate, this);
119
  this.collection.on('clear', this.afterClear, this);
120
  },
121
+
122
  maybe_make_sortable: function() {
123
  if (this.$('th.p2p-col-order').length) {
124
  this.$('tbody').sortable({
134
  });
135
  }
136
  },
137
+
138
  clear: function(ev) {
139
  var $td;
140
  ev.preventDefault();
145
  row_wait($td);
146
  this.collection.clear();
147
  },
148
+
149
  afterClear: function() {
150
  this.$el.hide().find('tbody').html('');
151
  },
152
+
153
  "delete": function(ev) {
154
  var $td, req;
155
  ev.preventDefault();
162
  remove_row($td);
163
  });
164
  },
165
+
166
  afterCreate: function(response) {
167
  this.$el.show().find('tbody').append(response.row);
168
  this.collection.trigger('append', response);
169
  }
170
  });
171
 
172
+ // View responsible for the candidate list
173
  CandidatesView = Backbone.View.extend({
174
+
175
  template: Mustache.compile(get_mustache_template('tab-list')),
176
+
177
  events: {
178
  'keypress :text': 'handleReturn',
179
  'keyup :text': 'handleSearch',
180
  'click .p2p-prev, .p2p-next': 'changePage',
181
  'click td.p2p-col-create div': 'promote'
182
  },
183
+
184
  initialize: function(options) {
185
  this.options = options;
186
  this.spinner = options.spinner;
190
  this.collection.on('error', this.afterInvalid, this);
191
  this.collection.on('invalid', this.afterInvalid, this);
192
  },
193
+
194
  promote: function(ev) {
195
  var $td, req, _this = this;
196
  ev.preventDefault();
208
  }
209
  });
210
  },
211
+
212
  handleReturn: function(ev) {
213
  if (ev.keyCode === ENTER_KEY) {
214
  ev.preventDefault();
215
  }
216
  },
217
+
218
  handleSearch: function(ev) {
219
  var $searchInput, delayed,
220
  _this = this;
235
  });
236
  }, 400);
237
  },
238
+
239
  changePage: function(ev) {
240
  var $navButton, new_page;
241
  $navButton = jQuery(ev.currentTarget);
248
  this.spinner.appendTo(this.$('.p2p-navigation'));
249
  this.collection.save('paged', new_page);
250
  },
251
+
252
  afterCandidatesRefreshed: function(response) {
253
  this.spinner.remove();
254
  this.$('button, .p2p-results, .p2p-navigation, .p2p-notice').remove();
262
  }
263
  });
264
 
265
+ // View responsible for the post creation UI
266
  CreatePostView = Backbone.View.extend({
267
+
268
  events: {
269
  'click button': 'createItem',
270
  'keypress :text': 'handleReturn'
271
  },
272
+
273
  initialize: function(options) {
274
  this.options = options;
275
  this.createButton = this.$('button');
276
  this.createInput = this.$(':text');
277
  },
278
+
279
  handleReturn: function(ev) {
280
  if (ev.keyCode === ENTER_KEY) {
281
  this.createButton.click();
282
  ev.preventDefault();
283
  }
284
  },
285
+
286
  createItem: function(ev) {
287
  var req, title, _this = this;
288
  ev.preventDefault();
303
  }
304
  });
305
 
306
+ // View responsible for the entire metabox
307
  MetaboxView = Backbone.View.extend({
308
+
309
  events: {
310
  'click .p2p-toggle-tabs': 'toggleTabs',
311
  'click .wp-tab-bar li': 'setActiveTab'
312
  },
313
+
314
  initialize: function(options) {
315
  this.options = options;
316
  this.spinner = options.spinner;
319
  options.connections.on('clear', this.afterConnectionDeleted, this);
320
  options.connections.on('delete', this.afterConnectionDeleted, this);
321
  },
322
+
323
  toggleTabs: function(ev) {
324
  var $tabs;
325
  ev.preventDefault();
330
  this.initializedCandidates = true;
331
  }
332
  },
333
+
334
  setActiveTab: function(ev) {
335
  var $tab;
336
  ev.preventDefault();
339
  $tab.addClass('wp-tab-active');
340
  this.$el.find('.tabs-panel').hide().end().find($tab.data('ref')).show().find(':text').focus();
341
  },
342
+
343
  afterConnectionAppended: function(response) {
344
  if ('one' === this.options.cardinality) {
345
  this.$('.p2p-create-connections').hide();
346
  }
347
  },
348
+
349
  afterConnectionDeleted: function(response) {
350
  if ('one' === this.options.cardinality) {
351
  this.$('.p2p-create-connections').show();
360
  };
361
 
362
  jQuery(function() {
363
+ // Polyfill for browsers that don't support the placeholder attribute
364
  if (!jQuery('<input placeholder="1" />')[0].placeholder) {
365
+ function setVal() {
366
  var $this;
367
  $this = jQuery(this);
368
  if (!$this.val()) {
370
  $this.addClass('p2p-placeholder');
371
  }
372
  };
373
+
374
+ function clearVal() {
375
  var $this;
376
  $this = jQuery(this);
377
  if ($this.hasClass('p2p-placeholder')) {
386
 
387
  jQuery('.p2p-box').each(function() {
388
  var $metabox, $spinner, candidates, candidatesView, connections, connectionsView, createPostView, ctype, metaboxView;
389
+
390
  $metabox = jQuery(this);
391
+
392
  $spinner = jQuery('<img>', {
393
  'src': P2PAdminL10n.spinner,
394
  'class': 'p2p-spinner'
395
  });
396
+
397
  candidates = new Candidates({
398
  's': '',
399
  'paged': 1
400
  });
401
  candidates.total_pages = $metabox.find('.p2p-total').data('num') || 1;
402
+
403
  ctype = {
404
  p2p_type: $metabox.data('p2p_type'),
405
  direction: $metabox.data('direction'),
406
  from: jQuery('#post_ID').val()
407
  };
408
 
409
+ // All ajax requests should be done through this function
410
  function ajax_request(options, callback) {
411
  var params = _.extend({}, options, candidates.attributes, ctype, {
412
  action: 'p2p_box',
436
 
437
  connections = new Connections();
438
  connections.ajax_request = ajax_request;
439
+
440
  connectionsView = new ConnectionsView({
441
  el: $metabox.find('.p2p-connections'),
442
  collection: connections,
admin/column-post.php CHANGED
@@ -24,7 +24,9 @@ class P2P_Column_Post extends P2P_Column {
24
  'post_type' => get_current_screen()->post_type
25
  );
26
 
27
- return add_query_arg( $args, admin_url( 'edit.php' ) );
 
 
28
  }
29
 
30
  function display_column( $column, $item_id ) {
24
  'post_type' => get_current_screen()->post_type
25
  );
26
 
27
+ $admin_link = apply_filters( "p2p_post_admin_column_link", add_query_arg( $args, admin_url( 'edit.php' ) ), $item );
28
+
29
+ return $admin_link;
30
  }
31
 
32
  function display_column( $column, $item_id ) {
admin/column-user.php CHANGED
@@ -36,7 +36,9 @@ class P2P_Column_User extends P2P_Column {
36
  'connected_items' => $item->get_id(),
37
  );
38
 
39
- return add_query_arg( $args, admin_url( 'users.php' ) );
 
 
40
  }
41
 
42
  function display_column( $content, $column, $item_id ) {
36
  'connected_items' => $item->get_id(),
37
  );
38
 
39
+ $admin_link = apply_filters( "p2p_user_admin_column_link", add_query_arg( $args, admin_url( 'users.php' ) ), $item );
40
+
41
+ return $admin_link;
42
  }
43
 
44
  function display_column( $content, $column, $item_id ) {
admin/mustache.php CHANGED
@@ -5,25 +5,20 @@
5
  */
6
  abstract class P2P_Mustache {
7
 
8
- private static $loader;
9
  private static $mustache;
10
 
11
  public static function init() {
12
- if ( !class_exists( 'Mustache' ) )
13
- require dirname(__FILE__) . '/../mustache/Mustache.php';
14
 
15
- if ( !class_exists( 'MustacheLoader' ) )
16
- require dirname(__FILE__) . '/../mustache/MustacheLoader.php';
17
-
18
- self::$loader = new MustacheLoader( dirname(__FILE__) . '/templates', 'html' );
19
-
20
- self::$mustache = new Mustache( null, null, self::$loader );
21
  }
22
 
23
  public static function render( $template, $data ) {
24
- return self::$mustache->render( self::$loader[$template], $data );
25
  }
26
  }
27
 
28
- P2P_Mustache::init();
29
-
5
  */
6
  abstract class P2P_Mustache {
7
 
 
8
  private static $mustache;
9
 
10
  public static function init() {
11
+ $loader = new Mustache_Loader_FilesystemLoader(
12
+ dirname(__FILE__) . '/templates', array( 'extension' => 'html' ) );
13
 
14
+ self::$mustache = new Mustache_Engine( array(
15
+ 'loader' => $loader,
16
+ 'partials_loader' => $loader
17
+ ) );
 
 
18
  }
19
 
20
  public static function render( $template, $data ) {
21
+ return self::$mustache->render( $template, $data );
22
  }
23
  }
24
 
 
 
composer.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "scribu/posts-to-posts",
3
+ "type": "wordpress-plugin",
4
+ "homepage": "http://wordpress.org/plugins/posts-to-posts",
5
+ "license": "GPL-2.0+",
6
+ "minimum-stability": "dev",
7
+ "require": {
8
+ "composer/installers": "~1.0",
9
+ "scribu/lib-posts-to-posts": "dev-master",
10
+ "mustache/mustache": "~2.6"
11
+ },
12
+ "repositories": [
13
+ {
14
+ "type": "vcs",
15
+ "url": "https://github.com/scribu/wp-lib-posts-to-posts"
16
+ }
17
+ ]
18
+ }
core/init.php DELETED
@@ -1,18 +0,0 @@
1
- <?php
2
-
3
- require_once dirname( __FILE__ ) . '/util.php';
4
- require_once dirname( __FILE__ ) . '/api.php';
5
- require_once dirname( __FILE__ ) . '/autoload.php';
6
-
7
- P2P_Autoload::register( 'P2P_', dirname( __FILE__ ) );
8
-
9
- P2P_Storage::init();
10
-
11
- P2P_Query_Post::init();
12
- P2P_Query_User::init();
13
-
14
- P2P_URL_Query::init();
15
-
16
- P2P_Widget::init();
17
- P2P_Shortcodes::init();
18
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lang/posts-to-posts-da_DK.mo ADDED
Binary file
lang/posts-to-posts-da_DK.po ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2013
2
+ # This file is distributed under the same license as the package.
3
+ msgid ""
4
+ msgstr ""
5
+ "Project-Id-Version: Posts 2 Posts\n"
6
+ "Report-Msgid-Bugs-To: http://wordpress.org/tag/p2p\n"
7
+ "POT-Creation-Date: 2013-02-17 08:06:11+00:00\n"
8
+ "MIME-Version: 1.0\n"
9
+ "Content-Type: text/plain; charset=UTF-8\n"
10
+ "Content-Transfer-Encoding: 8bit\n"
11
+ "PO-Revision-Date: 2014-10-07 15:48+0100\n"
12
+ "Last-Translator: Phh <phh@peytz.dk>\n"
13
+ "Language-Team: \n"
14
+ "X-Generator: Poedit 1.6.9\n"
15
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
16
+ "Language: da\n"
17
+
18
+ #: admin/box.php:45
19
+ msgid "Are you sure you want to delete all connections?"
20
+ msgstr "Er du sikker på du vil slette alle forbindelser?"
21
+
22
+ #: admin/box.php:136
23
+ msgid "Search"
24
+ msgstr "Søg"
25
+
26
+ #: admin/box.php:213
27
+ msgid "previous"
28
+ msgstr "forrige"
29
+
30
+ #: admin/box.php:214
31
+ msgid "next"
32
+ msgstr "næste"
33
+
34
+ #: admin/box.php:215
35
+ msgid "of"
36
+ msgstr "af"
37
+
38
+ #: admin/dropdown-user.php:32
39
+ msgid "Filter"
40
+ msgstr "Filter"
41
+
42
+ #: admin/factory.php:88
43
+ msgid " (from)"
44
+ msgstr " (fra)"
45
+
46
+ #: admin/factory.php:89
47
+ msgid " (to)"
48
+ msgstr " (til)"
49
+
50
+ #: admin/field-delete.php:7
51
+ msgid "Delete all connections"
52
+ msgstr "Slet alle forbindelser"
53
+
54
+ #: admin/field-delete.php:16
55
+ msgid "Delete connection"
56
+ msgstr "Slet forbindelse"
57
+
58
+ #: admin/tools-page.php:7
59
+ msgid "Connection Types"
60
+ msgstr "Forbindelsestyper"
61
+
62
+ #: admin/tools-page.php:41
63
+ msgid "<em>%s</em> is not a registered connection type."
64
+ msgstr "<em>%s</em> er ikke en registreret forbindelsestype."
65
+
66
+ #: admin/tools-page.php:50
67
+ msgid "Converted %1$s connections from <em>%2$s</em> to <em>%3$s</em>."
68
+ msgstr "Konverterede %1$s forbindelser from <em>%2$s</em> til <em>%3$s</em>."
69
+
70
+ #: admin/tools-page.php:64
71
+ msgid "Name"
72
+ msgstr "Navn"
73
+
74
+ #: admin/tools-page.php:65
75
+ msgid "Information"
76
+ msgstr "Information"
77
+
78
+ #: admin/tools-page.php:66
79
+ msgid "Connections"
80
+ msgstr "Forbindelser"
81
+
82
+ #: admin/tools-page.php:74
83
+ msgid "No connection types registered."
84
+ msgstr "Ingen forbindelsestyper registreret."
85
+
86
+ #: admin/tools-page.php:76
87
+ msgid "To register a connection type, see <a href=\"%s\">the wiki</a>."
88
+ msgstr "For at registrere en forbindelsestype, se <a href=\"%s\">wiki'en</a>."
89
+
90
+ #: admin/tools-page.php:93
91
+ msgid "Convert to registered connection type:"
92
+ msgstr "Konverter til registreret forbindelsestype:"
93
+
94
+ #: admin/tools-page.php:129
95
+ msgid "Go"
96
+ msgstr "Start"
97
+
98
+ #: core/connection-type.php:102
99
+ msgid "Create connections"
100
+ msgstr "Opret forbindelser"
101
+
102
+ #: core/connection-type.php:120
103
+ msgid "Connected %s"
104
+ msgstr "Forbandt %s"
105
+
106
+ #: core/side-user.php:16
107
+ msgid "Users"
108
+ msgstr "Brugere"
109
+
110
+ #: core/side-user.php:25
111
+ msgid "User"
112
+ msgstr "Bruger"
113
+
114
+ #: core/side-user.php:26
115
+ msgid "Search Users"
116
+ msgstr "Søg Brugere"
117
+
118
+ #: core/side-user.php:27
119
+ msgid "No users found."
120
+ msgstr "Ingen brugere fundet."
121
+
122
+ #: core/widget.php:16
123
+ msgid "Posts 2 Posts"
124
+ msgstr "Posts 2 Posts"
125
+
126
+ #: core/widget.php:17
127
+ msgid "A list of posts connected to the current post"
128
+ msgstr "En liste af indlæg forbundet med det nuværende indlæg"
129
+
130
+ #: core/widget.php:34
131
+ msgid "Title:"
132
+ msgstr "Titel:"
133
+
134
+ #: core/widget.php:41
135
+ msgid "Connection type:"
136
+ msgstr "Forbindelsestype:"
137
+
138
+ #: core/widget.php:46
139
+ msgid "Connection listing:"
140
+ msgstr "Forbindelsesliste:"
141
+
142
+ #: core/widget.php:52
143
+ msgid "connected"
144
+ msgstr "forbundet"
145
+
146
+ #: core/widget.php:53
147
+ msgid "related"
148
+ msgstr "relateret"
149
+
150
+ #: scb/AdminPage.php:227
151
+ msgid "Settings <strong>saved</strong>."
152
+ msgstr "Indstillinger <strong>gemt</strong>."
153
+
154
+ #: scb/AdminPage.php:466
155
+ msgid "Settings"
156
+ msgstr "Indstillinger"
lang/posts-to-posts-sv_SE.mo CHANGED
Binary file
lang/posts-to-posts-sv_SE.po CHANGED
@@ -2,89 +2,164 @@
2
  # This file is distributed under the same license as the package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Posts 2 Posts\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/p2p\n"
7
- "POT-Creation-Date: 2011-09-24 13:12:56+00:00\n"
 
 
 
 
8
  "MIME-Version: 1.0\n"
9
- "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
11
- "PO-Revision-Date: 2011-10-17 12:17+0100\n"
12
- "Last-Translator: Joel Arvidsson <joel@oblador.se>\n"
13
- "Language-Team: \n"
14
- "X-Poedit-Language: Swedish\n"
15
- "X-Poedit-Country: SWEDEN\n"
16
- "X-Poedit-SourceCharset: utf-8\n"
17
-
18
- #: scb/AdminPage.php:163
19
- msgid "Settings <strong>saved</strong>."
20
- msgstr "Inställningar <strong>sparade</strong>."
21
 
22
- #: scb/AdminPage.php:176
23
- #: scb/AdminPage.php:187
24
- msgid "Save Changes"
25
- msgstr "Spara ändringar"
26
 
27
- #: scb/AdminPage.php:348
28
- msgid "Settings"
29
- msgstr "Inställningar"
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
- #: admin/fields.php:13
32
- msgid "Create connection"
33
- msgstr "Skapa koppling"
34
 
35
- #: admin/fields.php:25
 
 
 
 
 
 
 
 
36
  msgid "Delete all connections"
37
  msgstr "Radera alla kopplingar"
38
 
39
- #: admin/fields.php:34
40
  msgid "Delete connection"
41
  msgstr "Radera koppling"
42
 
43
- #: admin/box.php:59
44
- msgid "Are you sure you want to delete all connections?"
45
- msgstr "Är du säker på att du vill radera alla kopplingar?"
46
 
47
- #: admin/box.php:69
48
- msgid "Connected %s"
49
- msgstr "Kopplad %s"
50
 
51
- #: admin/box.php:116
52
- msgid "Create connections:"
53
- msgstr "Skapa kopplingar: "
54
 
55
- #: admin/box.php:125
56
- msgid "Search"
57
- msgstr "Sök"
58
 
59
- #: admin/box.php:133
60
- msgid "View All"
61
- msgstr "Visa alla"
62
 
63
- #: admin/box.php:216
64
- msgid "previous"
65
- msgstr "föregående"
66
 
67
- #: admin/box.php:217
68
- msgid "next"
69
- msgstr "nästa"
70
 
71
- #: admin/box.php:218
72
- msgid "of"
73
- msgstr "av"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
 
75
- #: core/widget.php:14
76
  msgid "Posts 2 Posts"
77
- msgstr ""
78
 
79
- #: core/widget.php:15
80
  msgid "A list of posts connected to the current post"
81
  msgstr "En lista över inlägg kopplade till aktuellt inlägg"
82
 
83
- #: core/widget.php:29
 
 
 
 
84
  msgid "Connection type:"
85
  msgstr "Kopplingstyp: "
86
 
 
 
 
 
 
 
 
 
87
  #: core/widget.php:53
88
- msgid "Related %s"
89
- msgstr "Relaterade %s"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
 
 
2
  # This file is distributed under the same license as the package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Posts 2 Posts sv_SE\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/p2p\n"
7
+ "POT-Creation-Date: 2013-02-17 08:06:11+00:00\n"
8
+ "PO-Revision-Date: 2014-04-10 12:33+0100\n"
9
+ "Last-Translator: Mattias Tengblad <mst@eyesx.com>\n"
10
+ "Language-Team: WordPress Sverige <info@wpsv.se>\n"
11
+ "Language: sv_SE\n"
12
  "MIME-Version: 1.0\n"
13
+ "Content-Type: text/plain; charset=UTF-8\n"
14
  "Content-Transfer-Encoding: 8bit\n"
15
+ "X-Poedit-SourceCharset: UTF-8\n"
16
+ "X-Generator: Poedit 1.6.4\n"
 
 
 
 
 
 
 
 
17
 
18
+ #: admin/box.php:45
19
+ msgid "Are you sure you want to delete all connections?"
20
+ msgstr "Är du säker på att du vill radera alla kopplingar?"
 
21
 
22
+ #: admin/box.php:136
23
+ msgid "Search"
24
+ msgstr "Sök"
25
+
26
+ #: admin/box.php:213
27
+ msgid "previous"
28
+ msgstr "föregående"
29
+
30
+ #: admin/box.php:214
31
+ msgid "next"
32
+ msgstr "nästa"
33
+
34
+ #: admin/box.php:215
35
+ msgid "of"
36
+ msgstr "av"
37
 
38
+ #: admin/dropdown-user.php:32
39
+ msgid "Filter"
40
+ msgstr "Filtrera"
41
 
42
+ #: admin/factory.php:88
43
+ msgid " (from)"
44
+ msgstr "(från)"
45
+
46
+ #: admin/factory.php:89
47
+ msgid " (to)"
48
+ msgstr " (till)"
49
+
50
+ #: admin/field-delete.php:7
51
  msgid "Delete all connections"
52
  msgstr "Radera alla kopplingar"
53
 
54
+ #: admin/field-delete.php:16
55
  msgid "Delete connection"
56
  msgstr "Radera koppling"
57
 
58
+ #: admin/tools-page.php:7
59
+ msgid "Connection Types"
60
+ msgstr "Kopplingstyper"
61
 
62
+ #: admin/tools-page.php:41
63
+ msgid "<em>%s</em> is not a registered connection type."
64
+ msgstr "<em>%s</em> är inte en registrerad kopplingstyp."
65
 
66
+ #: admin/tools-page.php:50
67
+ msgid "Converted %1$s connections from <em>%2$s</em> to <em>%3$s</em>."
68
+ msgstr "Konverterade %1$s kopplingar från <em>%2$s</em> till <em>%3$s</em>."
69
 
70
+ #: admin/tools-page.php:64
71
+ msgid "Name"
72
+ msgstr "Namn"
73
 
74
+ #: admin/tools-page.php:65
75
+ msgid "Information"
76
+ msgstr "Information"
77
 
78
+ #: admin/tools-page.php:66
79
+ msgid "Connections"
80
+ msgstr "Kopplingar"
81
 
82
+ #: admin/tools-page.php:74
83
+ msgid "No connection types registered."
84
+ msgstr "Inga kopplingstyper registrerade."
85
 
86
+ #: admin/tools-page.php:76
87
+ msgid "To register a connection type, see <a href=\"%s\">the wiki</a>."
88
+ msgstr "För att registrera en kopplingstyp, se <a href=\"%s\">wikin</a>."
89
+
90
+ #: admin/tools-page.php:93
91
+ msgid "Convert to registered connection type:"
92
+ msgstr "Konvertera till registrerad kopplingstyp:"
93
+
94
+ #: admin/tools-page.php:129
95
+ msgid "Go"
96
+ msgstr "Ok"
97
+
98
+ #: core/connection-type.php:102
99
+ msgid "Create connections"
100
+ msgstr "Skapa kopplingar"
101
+
102
+ #: core/connection-type.php:120
103
+ msgid "Connected %s"
104
+ msgstr "Kopplad till %s"
105
+
106
+ #: core/side-user.php:16
107
+ msgid "Users"
108
+ msgstr "Användare"
109
+
110
+ #: core/side-user.php:25
111
+ msgid "User"
112
+ msgstr "Användare"
113
+
114
+ #: core/side-user.php:26
115
+ msgid "Search Users"
116
+ msgstr "Sök efter användare"
117
+
118
+ #: core/side-user.php:27
119
+ msgid "No users found."
120
+ msgstr "Inga användare funna."
121
 
122
+ #: core/widget.php:16
123
  msgid "Posts 2 Posts"
124
+ msgstr "Posts 2 Posts"
125
 
126
+ #: core/widget.php:17
127
  msgid "A list of posts connected to the current post"
128
  msgstr "En lista över inlägg kopplade till aktuellt inlägg"
129
 
130
+ #: core/widget.php:34
131
+ msgid "Title:"
132
+ msgstr "Titel:"
133
+
134
+ #: core/widget.php:41
135
  msgid "Connection type:"
136
  msgstr "Kopplingstyp: "
137
 
138
+ #: core/widget.php:46
139
+ msgid "Connection listing:"
140
+ msgstr "Kopplingslistning:"
141
+
142
+ #: core/widget.php:52
143
+ msgid "connected"
144
+ msgstr "kopplad"
145
+
146
  #: core/widget.php:53
147
+ msgid "related"
148
+ msgstr "relaterad"
149
+
150
+ #: scb/AdminPage.php:227
151
+ msgid "Settings <strong>saved</strong>."
152
+ msgstr "Inställningar <strong>sparade</strong>."
153
+
154
+ #: scb/AdminPage.php:466
155
+ msgid "Settings"
156
+ msgstr "Inställningar"
157
+
158
+ #~ msgid "Save Changes"
159
+ #~ msgstr "Spara ändringar"
160
+
161
+ #~ msgid "Create connection"
162
+ #~ msgstr "Skapa koppling"
163
 
164
+ #~ msgid "View All"
165
+ #~ msgstr "Visa alla"
lang/posts-to-posts-zh_CN.mo ADDED
Binary file
lang/posts-to-posts-zh_CN.po ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Posts 2 Posts\n"
4
+ "Report-Msgid-Bugs-To: http://wordpress.org/tag/p2p\n"
5
+ "POT-Creation-Date: 2013-02-17 08:06:11+00:00\n"
6
+ "PO-Revision-Date: \n"
7
+ "Last-Translator: Daniel Koskinen <daniel.koskinen@gmail.com>\n"
8
+ "Language-Team: Amos Lee <4626395@gmail.com>\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "Plural-Forms: nplurals=2; plural=n != 1;\n"
13
+ "X-Poedit-SourceCharset: UTF-8\n"
14
+ "Language: zh_CN\n"
15
+ "X-Generator: Poedit 1.7.5\n"
16
+
17
+ #: admin/box.php:45
18
+ msgid "Are you sure you want to delete all connections?"
19
+ msgstr "确定要删除所有连接吗?"
20
+
21
+ #: admin/box.php:136
22
+ msgid "Search"
23
+ msgstr "搜索."
24
+
25
+ #: admin/box.php:213
26
+ msgid "previous"
27
+ msgstr "上一个"
28
+
29
+ #: admin/box.php:214
30
+ msgid "next"
31
+ msgstr "下一个"
32
+
33
+ #: admin/box.php:215
34
+ msgid "of"
35
+ msgstr "/"
36
+
37
+ #: admin/dropdown-user.php:32
38
+ msgid "Filter"
39
+ msgstr "筛选"
40
+
41
+ #: admin/factory.php:88
42
+ msgid " (from)"
43
+ msgstr "从"
44
+
45
+ #: admin/factory.php:89
46
+ msgid " (to)"
47
+ msgstr "到"
48
+
49
+ #: admin/field-delete.php:7
50
+ msgid "Delete all connections"
51
+ msgstr "删除所有连接"
52
+
53
+ #: admin/field-delete.php:16
54
+ msgid "Delete connection"
55
+ msgstr "删除连接"
56
+
57
+ #: admin/tools-page.php:7
58
+ msgid "Connection Types"
59
+ msgstr "连接类型"
60
+
61
+ #: admin/tools-page.php:41
62
+ msgid "<em>%s</em> is not a registered connection type."
63
+ msgstr "<em>%s</em> 不是一个注册的连接类型"
64
+
65
+ #: admin/tools-page.php:50
66
+ msgid "Converted %1$s connections from <em>%2$s</em> to <em>%3$s</em>."
67
+ msgstr "从 <em>%2$s</em> 到 <em>%3$s</em>转换了 %1$s 个连接"
68
+
69
+ #: admin/tools-page.php:64
70
+ msgid "Name"
71
+ msgstr "名称"
72
+
73
+ #: admin/tools-page.php:65
74
+ msgid "Information"
75
+ msgstr "信息"
76
+
77
+ #: admin/tools-page.php:66
78
+ msgid "Connections"
79
+ msgstr "连接"
80
+
81
+ #: admin/tools-page.php:74
82
+ msgid "No connection types registered."
83
+ msgstr "没有注册连接类型"
84
+
85
+ #: admin/tools-page.php:76
86
+ msgid "To register a connection type, see <a href=\"%s\">the wiki</a>."
87
+ msgstr "需要注册连接类型,查看 <a href=\"%s\">wiki</a>."
88
+
89
+ #: admin/tools-page.php:93
90
+ msgid "Convert to registered connection type:"
91
+ msgstr "转换到已注册的连接类型:"
92
+
93
+ #: admin/tools-page.php:129
94
+ msgid "Go"
95
+ msgstr "转到"
96
+
97
+ #: core/connection-type.php:102
98
+ msgid "Create connections"
99
+ msgstr "创建连接"
100
+
101
+ #: core/connection-type.php:120
102
+ msgid "Connected %s"
103
+ msgstr "%s 已连接"
104
+
105
+ #: core/side-user.php:16
106
+ msgid "Users"
107
+ msgstr "用户"
108
+
109
+ #: core/side-user.php:25
110
+ msgid "User"
111
+ msgstr "用户"
112
+
113
+ #: core/side-user.php:26
114
+ msgid "Search Users"
115
+ msgstr "搜索用户"
116
+
117
+ #: core/side-user.php:27
118
+ msgid "No users found."
119
+ msgstr "没有找到用户"
120
+
121
+ #: core/widget.php:16
122
+ msgid "Posts 2 Posts"
123
+ msgstr "Posts 2 Posts"
124
+
125
+ #: core/widget.php:17
126
+ msgid "A list of posts connected to the current post"
127
+ msgstr "连接到本文的文章"
128
+
129
+ #: core/widget.php:34
130
+ msgid "Title:"
131
+ msgstr "标题:"
132
+
133
+ #: core/widget.php:41
134
+ msgid "Connection type:"
135
+ msgstr "连接类型:"
136
+
137
+ #: core/widget.php:46
138
+ msgid "Connection listing:"
139
+ msgstr "连接列表:"
140
+
141
+ #: core/widget.php:52
142
+ msgid "connected"
143
+ msgstr "已连接"
144
+
145
+ #: core/widget.php:53
146
+ msgid "related"
147
+ msgstr "相关"
148
+
149
+ #: scb/AdminPage.php:227
150
+ msgid "Settings <strong>saved</strong>."
151
+ msgstr "设置 <strong>已保存</strong>."
152
+
153
+ #: scb/AdminPage.php:466
154
+ msgid "Settings"
155
+ msgstr "设置"
mustache/LICENSE DELETED
@@ -1,22 +0,0 @@
1
- Copyright (c) 2010 Justin Hileman
2
-
3
- Permission is hereby granted, free of charge, to any person
4
- obtaining a copy of this software and associated documentation
5
- files (the "Software"), to deal in the Software without
6
- restriction, including without limitation the rights to use,
7
- copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- copies of the Software, and to permit persons to whom the
9
- Software is furnished to do so, subject to the following
10
- conditions:
11
-
12
- The above copyright notice and this permission notice shall be
13
- included in all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
- OTHER DEALINGS IN THE SOFTWARE.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mustache/Mustache.php DELETED
@@ -1,910 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * A Mustache implementation in PHP.
5
- *
6
- * {@link http://defunkt.github.com/mustache}
7
- *
8
- * Mustache is a framework-agnostic logic-less templating language. It enforces separation of view
9
- * logic from template files. In fact, it is not even possible to embed logic in the template.
10
- *
11
- * This is very, very rad.
12
- *
13
- * @author Justin Hileman {@link http://justinhileman.com}
14
- */
15
- class Mustache {
16
-
17
- const VERSION = '1.0.0';
18
- const SPEC_VERSION = '1.1.2';
19
-
20
- /**
21
- * Should this Mustache throw exceptions when it finds unexpected tags?
22
- *
23
- * @see self::_throwsException()
24
- */
25
- protected $_throwsExceptions = array(
26
- MustacheException::UNKNOWN_VARIABLE => false,
27
- MustacheException::UNCLOSED_SECTION => true,
28
- MustacheException::UNEXPECTED_CLOSE_SECTION => true,
29
- MustacheException::UNKNOWN_PARTIAL => false,
30
- MustacheException::UNKNOWN_PRAGMA => true,
31
- );
32
-
33
- // Override charset passed to htmlentities() and htmlspecialchars(). Defaults to UTF-8.
34
- protected $_charset = 'UTF-8';
35
-
36
- /**
37
- * Pragmas are macro-like directives that, when invoked, change the behavior or
38
- * syntax of Mustache.
39
- *
40
- * They should be considered extremely experimental. Most likely their implementation
41
- * will change in the future.
42
- */
43
-
44
- /**
45
- * The {{%UNESCAPED}} pragma swaps the meaning of the {{normal}} and {{{unescaped}}}
46
- * Mustache tags. That is, once this pragma is activated the {{normal}} tag will not be
47
- * escaped while the {{{unescaped}}} tag will be escaped.
48
- *
49
- * Pragmas apply only to the current template. Partials, even those included after the
50
- * {{%UNESCAPED}} call, will need their own pragma declaration.
51
- *
52
- * This may be useful in non-HTML Mustache situations.
53
- */
54
- const PRAGMA_UNESCAPED = 'UNESCAPED';
55
-
56
- /**
57
- * Constants used for section and tag RegEx
58
- */
59
- const SECTION_TYPES = '\^#\/';
60
- const TAG_TYPES = '#\^\/=!<>\\{&';
61
-
62
- protected $_otag = '{{';
63
- protected $_ctag = '}}';
64
-
65
- protected $_tagRegEx;
66
-
67
- protected $_template = '';
68
- protected $_context = array();
69
- protected $_partials = array();
70
- protected $_pragmas = array();
71
-
72
- protected $_pragmasImplemented = array(
73
- self::PRAGMA_UNESCAPED
74
- );
75
-
76
- protected $_localPragmas = array();
77
-
78
- /**
79
- * Mustache class constructor.
80
- *
81
- * This method accepts a $template string and a $view object. Optionally, pass an associative
82
- * array of partials as well.
83
- *
84
- * Passing an $options array allows overriding certain Mustache options during instantiation:
85
- *
86
- * $options = array(
87
- * // `charset` -- must be supported by `htmlspecialentities()`. defaults to 'UTF-8'
88
- * 'charset' => 'ISO-8859-1',
89
- *
90
- * // opening and closing delimiters, as an array or a space-separated string
91
- * 'delimiters' => '<% %>',
92
- *
93
- * // an array of pragmas to enable/disable
94
- * 'pragmas' => array(
95
- * Mustache::PRAGMA_UNESCAPED => true
96
- * ),
97
- *
98
- * // an array of thrown exceptions to enable/disable
99
- * 'throws_exceptions' => array(
100
- * MustacheException::UNKNOWN_VARIABLE => false,
101
- * MustacheException::UNCLOSED_SECTION => true,
102
- * MustacheException::UNEXPECTED_CLOSE_SECTION => true,
103
- * MustacheException::UNKNOWN_PARTIAL => false,
104
- * MustacheException::UNKNOWN_PRAGMA => true,
105
- * ),
106
- * );
107
- *
108
- * @access public
109
- * @param string $template (default: null)
110
- * @param mixed $view (default: null)
111
- * @param array $partials (default: null)
112
- * @param array $options (default: array())
113
- * @return void
114
- */
115
- public function __construct($template = null, $view = null, $partials = null, array $options = null) {
116
- if ($template !== null) $this->_template = $template;
117
- if ($partials !== null) $this->_partials = $partials;
118
- if ($view !== null) $this->_context = array($view);
119
- if ($options !== null) $this->_setOptions($options);
120
- }
121
-
122
- /**
123
- * Helper function for setting options from constructor args.
124
- *
125
- * @access protected
126
- * @param array $options
127
- * @return void
128
- */
129
- protected function _setOptions(array $options) {
130
- if (isset($options['charset'])) {
131
- $this->_charset = $options['charset'];
132
- }
133
-
134
- if (isset($options['delimiters'])) {
135
- $delims = $options['delimiters'];
136
- if (!is_array($delims)) {
137
- $delims = array_map('trim', explode(' ', $delims, 2));
138
- }
139
- $this->_otag = $delims[0];
140
- $this->_ctag = $delims[1];
141
- }
142
-
143
- if (isset($options['pragmas'])) {
144
- foreach ($options['pragmas'] as $pragma_name => $pragma_value) {
145
- if (!in_array($pragma_name, $this->_pragmasImplemented, true)) {
146
- throw new MustacheException('Unknown pragma: ' . $pragma_name, MustacheException::UNKNOWN_PRAGMA);
147
- }
148
- }
149
- $this->_pragmas = $options['pragmas'];
150
- }
151
-
152
- if (isset($options['throws_exceptions'])) {
153
- foreach ($options['throws_exceptions'] as $exception => $value) {
154
- $this->_throwsExceptions[$exception] = $value;
155
- }
156
- }
157
- }
158
-
159
- /**
160
- * Mustache class clone method.
161
- *
162
- * A cloned Mustache instance should have pragmas, delimeters and root context
163
- * reset to default values.
164
- *
165
- * @access public
166
- * @return void
167
- */
168
- public function __clone() {
169
- $this->_otag = '{{';
170
- $this->_ctag = '}}';
171
- $this->_localPragmas = array();
172
-
173
- if ($keys = array_keys($this->_context)) {
174
- $last = array_pop($keys);
175
- if ($this->_context[$last] instanceof Mustache) {
176
- $this->_context[$last] =& $this;
177
- }
178
- }
179
- }
180
-
181
- /**
182
- * Render the given template and view object.
183
- *
184
- * Defaults to the template and view passed to the class constructor unless a new one is provided.
185
- * Optionally, pass an associative array of partials as well.
186
- *
187
- * @access public
188
- * @param string $template (default: null)
189
- * @param mixed $view (default: null)
190
- * @param array $partials (default: null)
191
- * @return string Rendered Mustache template.
192
- */
193
- public function render($template = null, $view = null, $partials = null) {
194
- if ($template === null) $template = $this->_template;
195
- if ($partials !== null) $this->_partials = $partials;
196
-
197
- $otag_orig = $this->_otag;
198
- $ctag_orig = $this->_ctag;
199
-
200
- if ($view) {
201
- $this->_context = array($view);
202
- } else if (empty($this->_context)) {
203
- $this->_context = array($this);
204
- }
205
-
206
- $template = $this->_renderPragmas($template);
207
- $template = $this->_renderTemplate($template);
208
-
209
- $this->_otag = $otag_orig;
210
- $this->_ctag = $ctag_orig;
211
-
212
- return $template;
213
- }
214
-
215
- /**
216
- * Wrap the render() function for string conversion.
217
- *
218
- * @access public
219
- * @return string
220
- */
221
- public function __toString() {
222
- // PHP doesn't like exceptions in __toString.
223
- // catch any exceptions and convert them to strings.
224
- try {
225
- $result = $this->render();
226
- return $result;
227
- } catch (Exception $e) {
228
- return "Error rendering mustache: " . $e->getMessage();
229
- }
230
- }
231
-
232
- /**
233
- * Internal render function, used for recursive calls.
234
- *
235
- * @access protected
236
- * @param string $template
237
- * @return string Rendered Mustache template.
238
- */
239
- protected function _renderTemplate($template) {
240
- if ($section = $this->_findSection($template)) {
241
- list($before, $type, $tag_name, $content, $after) = $section;
242
-
243
- $rendered_before = $this->_renderTags($before);
244
-
245
- $rendered_content = '';
246
- $val = $this->_getVariable($tag_name);
247
- switch($type) {
248
- // inverted section
249
- case '^':
250
- if (empty($val)) {
251
- $rendered_content = $this->_renderTemplate($content);
252
- }
253
- break;
254
-
255
- // regular section
256
- case '#':
257
- // higher order sections
258
- if ($this->_varIsCallable($val)) {
259
- $rendered_content = $this->_renderTemplate(call_user_func($val, $content));
260
- } else if ($this->_varIsIterable($val)) {
261
- foreach ($val as $local_context) {
262
- $this->_pushContext($local_context);
263
- $rendered_content .= $this->_renderTemplate($content);
264
- $this->_popContext();
265
- }
266
- } else if ($val) {
267
- if (is_array($val) || is_object($val)) {
268
- $this->_pushContext($val);
269
- $rendered_content = $this->_renderTemplate($content);
270
- $this->_popContext();
271
- } else {
272
- $rendered_content = $this->_renderTemplate($content);
273
- }
274
- }
275
- break;
276
- }
277
-
278
- return $rendered_before . $rendered_content . $this->_renderTemplate($after);
279
- }
280
-
281
- return $this->_renderTags($template);
282
- }
283
-
284
- /**
285
- * Prepare a section RegEx string for the given opening/closing tags.
286
- *
287
- * @access protected
288
- * @param string $otag
289
- * @param string $ctag
290
- * @return string
291
- */
292
- protected function _prepareSectionRegEx($otag, $ctag) {
293
- return sprintf(
294
- '/(?:(?<=\\n)[ \\t]*)?%s(?:(?P<type>[%s])(?P<tag_name>.+?)|=(?P<delims>.*?)=)%s\\n?/s',
295
- preg_quote($otag, '/'),
296
- self::SECTION_TYPES,
297
- preg_quote($ctag, '/')
298
- );
299
- }
300
-
301
- /**
302
- * Extract the first section from $template.
303
- *
304
- * @access protected
305
- * @param string $template
306
- * @return array $before, $type, $tag_name, $content and $after
307
- */
308
- protected function _findSection($template) {
309
- $regEx = $this->_prepareSectionRegEx($this->_otag, $this->_ctag);
310
-
311
- $section_start = null;
312
- $section_type = null;
313
- $content_start = null;
314
-
315
- $search_offset = 0;
316
-
317
- $section_stack = array();
318
- $matches = array();
319
- while (preg_match($regEx, $template, $matches, PREG_OFFSET_CAPTURE, $search_offset)) {
320
- if (isset($matches['delims'][0])) {
321
- list($otag, $ctag) = explode(' ', $matches['delims'][0]);
322
- $regEx = $this->_prepareSectionRegEx($otag, $ctag);
323
- $search_offset = $matches[0][1] + strlen($matches[0][0]);
324
- continue;
325
- }
326
-
327
- $match = $matches[0][0];
328
- $offset = $matches[0][1];
329
- $type = $matches['type'][0];
330
- $tag_name = trim($matches['tag_name'][0]);
331
-
332
- $search_offset = $offset + strlen($match);
333
-
334
- switch ($type) {
335
- case '^':
336
- case '#':
337
- if (empty($section_stack)) {
338
- $section_start = $offset;
339
- $section_type = $type;
340
- $content_start = $search_offset;
341
- }
342
- array_push($section_stack, $tag_name);
343
- break;
344
- case '/':
345
- if (empty($section_stack) || ($tag_name !== array_pop($section_stack))) {
346
- if ($this->_throwsException(MustacheException::UNEXPECTED_CLOSE_SECTION)) {
347
- throw new MustacheException('Unexpected close section: ' . $tag_name, MustacheException::UNEXPECTED_CLOSE_SECTION);
348
- }
349
- }
350
-
351
- if (empty($section_stack)) {
352
- // $before, $type, $tag_name, $content, $after
353
- return array(
354
- substr($template, 0, $section_start),
355
- $section_type,
356
- $tag_name,
357
- substr($template, $content_start, $offset - $content_start),
358
- substr($template, $search_offset),
359
- );
360
- }
361
- break;
362
- }
363
- }
364
-
365
- if (!empty($section_stack)) {
366
- if ($this->_throwsException(MustacheException::UNCLOSED_SECTION)) {
367
- throw new MustacheException('Unclosed section: ' . $section_stack[0], MustacheException::UNCLOSED_SECTION);
368
- }
369
- }
370
- }
371
-
372
- /**
373
- * Prepare a pragma RegEx for the given opening/closing tags.
374
- *
375
- * @access protected
376
- * @param string $otag
377
- * @param string $ctag
378
- * @return string
379
- */
380
- protected function _preparePragmaRegEx($otag, $ctag) {
381
- return sprintf(
382
- '/%s%%\\s*(?P<pragma_name>[\\w_-]+)(?P<options_string>(?: [\\w]+=[\\w]+)*)\\s*%s\\n?/s',
383
- preg_quote($otag, '/'),
384
- preg_quote($ctag, '/')
385
- );
386
- }
387
-
388
- /**
389
- * Initialize pragmas and remove all pragma tags.
390
- *
391
- * @access protected
392
- * @param string $template
393
- * @return string
394
- */
395
- protected function _renderPragmas($template) {
396
- $this->_localPragmas = $this->_pragmas;
397
-
398
- // no pragmas
399
- if (strpos($template, $this->_otag . '%') === false) {
400
- return $template;
401
- }
402
-
403
- $regEx = $this->_preparePragmaRegEx($this->_otag, $this->_ctag);
404
- return preg_replace_callback($regEx, array($this, '_renderPragma'), $template);
405
- }
406
-
407
- /**
408
- * A preg_replace helper to remove {{%PRAGMA}} tags and enable requested pragma.
409
- *
410
- * @access protected
411
- * @param mixed $matches
412
- * @return void
413
- * @throws MustacheException unknown pragma
414
- */
415
- protected function _renderPragma($matches) {
416
- $pragma = $matches[0];
417
- $pragma_name = $matches['pragma_name'];
418
- $options_string = $matches['options_string'];
419
-
420
- if (!in_array($pragma_name, $this->_pragmasImplemented)) {
421
- if ($this->_throwsException(MustacheException::UNKNOWN_PRAGMA)) {
422
- throw new MustacheException('Unknown pragma: ' . $pragma_name, MustacheException::UNKNOWN_PRAGMA);
423
- } else {
424
- return '';
425
- }
426
- }
427
-
428
- $options = array();
429
- foreach (explode(' ', trim($options_string)) as $o) {
430
- if ($p = trim($o)) {
431
- $p = explode('=', $p);
432
- $options[$p[0]] = $p[1];
433
- }
434
- }
435
-
436
- if (empty($options)) {
437
- $this->_localPragmas[$pragma_name] = true;
438
- } else {
439
- $this->_localPragmas[$pragma_name] = $options;
440
- }
441
-
442
- return '';
443
- }
444
-
445
- /**
446
- * Check whether this Mustache has a specific pragma.
447
- *
448
- * @access protected
449
- * @param string $pragma_name
450
- * @return bool
451
- */
452
- protected function _hasPragma($pragma_name) {
453
- if (array_key_exists($pragma_name, $this->_localPragmas) && $this->_localPragmas[$pragma_name]) {
454
- return true;
455
- } else {
456
- return false;
457
- }
458
- }
459
-
460
- /**
461
- * Return pragma options, if any.
462
- *
463
- * @access protected
464
- * @param string $pragma_name
465
- * @return mixed
466
- * @throws MustacheException Unknown pragma
467
- */
468
- protected function _getPragmaOptions($pragma_name) {
469
- if (!$this->_hasPragma($pragma_name)) {
470
- if ($this->_throwsException(MustacheException::UNKNOWN_PRAGMA)) {
471
- throw new MustacheException('Unknown pragma: ' . $pragma_name, MustacheException::UNKNOWN_PRAGMA);
472
- }
473
- }
474
-
475
- return (is_array($this->_localPragmas[$pragma_name])) ? $this->_localPragmas[$pragma_name] : array();
476
- }
477
-
478
- /**
479
- * Check whether this Mustache instance throws a given exception.
480
- *
481
- * Expects exceptions to be MustacheException error codes (i.e. class constants).
482
- *
483
- * @access protected
484
- * @param mixed $exception
485
- * @return void
486
- */
487
- protected function _throwsException($exception) {
488
- return (isset($this->_throwsExceptions[$exception]) && $this->_throwsExceptions[$exception]);
489
- }
490
-
491
- /**
492
- * Prepare a tag RegEx for the given opening/closing tags.
493
- *
494
- * @access protected
495
- * @param string $otag
496
- * @param string $ctag
497
- * @return string
498
- */
499
- protected function _prepareTagRegEx($otag, $ctag, $first = false) {
500
- return sprintf(
501
- '/(?P<leading>(?:%s\\r?\\n)[ \\t]*)?%s(?P<type>[%s]?)(?P<tag_name>.+?)(?:\\2|})?%s(?P<trailing>\\s*(?:\\r?\\n|\\Z))?/s',
502
- ($first ? '\\A|' : ''),
503
- preg_quote($otag, '/'),
504
- self::TAG_TYPES,
505
- preg_quote($ctag, '/')
506
- );
507
- }
508
-
509
- /**
510
- * Loop through and render individual Mustache tags.
511
- *
512
- * @access protected
513
- * @param string $template
514
- * @return void
515
- */
516
- protected function _renderTags($template) {
517
- if (strpos($template, $this->_otag) === false) {
518
- return $template;
519
- }
520
-
521
- $first = true;
522
- $this->_tagRegEx = $this->_prepareTagRegEx($this->_otag, $this->_ctag, true);
523
-
524
- $html = '';
525
- $matches = array();
526
- while (preg_match($this->_tagRegEx, $template, $matches, PREG_OFFSET_CAPTURE)) {
527
- $tag = $matches[0][0];
528
- $offset = $matches[0][1];
529
- $modifier = $matches['type'][0];
530
- $tag_name = trim($matches['tag_name'][0]);
531
-
532
- if (isset($matches['leading']) && $matches['leading'][1] > -1) {
533
- $leading = $matches['leading'][0];
534
- } else {
535
- $leading = null;
536
- }
537
-
538
- if (isset($matches['trailing']) && $matches['trailing'][1] > -1) {
539
- $trailing = $matches['trailing'][0];
540
- } else {
541
- $trailing = null;
542
- }
543
-
544
- $html .= substr($template, 0, $offset);
545
-
546
- $next_offset = $offset + strlen($tag);
547
- if ((substr($html, -1) == "\n") && (substr($template, $next_offset, 1) == "\n")) {
548
- $next_offset++;
549
- }
550
- $template = substr($template, $next_offset);
551
-
552
- $html .= $this->_renderTag($modifier, $tag_name, $leading, $trailing);
553
-
554
- if ($first == true) {
555
- $first = false;
556
- $this->_tagRegEx = $this->_prepareTagRegEx($this->_otag, $this->_ctag);
557
- }
558
- }
559
-
560
- return $html . $template;
561
- }
562
-
563
- /**
564
- * Render the named tag, given the specified modifier.
565
- *
566
- * Accepted modifiers are `=` (change delimiter), `!` (comment), `>` (partial)
567
- * `{` or `&` (don't escape output), or none (render escaped output).
568
- *
569
- * @access protected
570
- * @param string $modifier
571
- * @param string $tag_name
572
- * @param string $leading Whitespace
573
- * @param string $trailing Whitespace
574
- * @throws MustacheException Unmatched section tag encountered.
575
- * @return string
576
- */
577
- protected function _renderTag($modifier, $tag_name, $leading, $trailing) {
578
- switch ($modifier) {
579
- case '=':
580
- return $this->_changeDelimiter($tag_name, $leading, $trailing);
581
- break;
582
- case '!':
583
- return $this->_renderComment($tag_name, $leading, $trailing);
584
- break;
585
- case '>':
586
- case '<':
587
- return $this->_renderPartial($tag_name, $leading, $trailing);
588
- break;
589
- case '{':
590
- // strip the trailing } ...
591
- if ($tag_name[(strlen($tag_name) - 1)] == '}') {
592
- $tag_name = substr($tag_name, 0, -1);
593
- }
594
- case '&':
595
- if ($this->_hasPragma(self::PRAGMA_UNESCAPED)) {
596
- return $this->_renderEscaped($tag_name, $leading, $trailing);
597
- } else {
598
- return $this->_renderUnescaped($tag_name, $leading, $trailing);
599
- }
600
- break;
601
- case '#':
602
- case '^':
603
- case '/':
604
- // remove any leftover section tags
605
- return $leading . $trailing;
606
- break;
607
- default:
608
- if ($this->_hasPragma(self::PRAGMA_UNESCAPED)) {
609
- return $this->_renderUnescaped($modifier . $tag_name, $leading, $trailing);
610
- } else {
611
- return $this->_renderEscaped($modifier . $tag_name, $leading, $trailing);
612
- }
613
- break;
614
- }
615
- }
616
-
617
- /**
618
- * Returns true if any of its args contains the "\r" character.
619
- *
620
- * @access protected
621
- * @param string $str
622
- * @return boolean
623
- */
624
- protected function _stringHasR($str) {
625
- foreach (func_get_args() as $arg) {
626
- if (strpos($arg, "\r") !== false) {
627
- return true;
628
- }
629
- }
630
- return false;
631
- }
632
-
633
- /**
634
- * Escape and return the requested tag.
635
- *
636
- * @access protected
637
- * @param string $tag_name
638
- * @param string $leading Whitespace
639
- * @param string $trailing Whitespace
640
- * @return string
641
- */
642
- protected function _renderEscaped($tag_name, $leading, $trailing) {
643
- $rendered = htmlentities($this->_renderUnescaped($tag_name, '', ''), ENT_COMPAT, $this->_charset);
644
- return $leading . $rendered . $trailing;
645
- }
646
-
647
- /**
648
- * Render a comment (i.e. return an empty string).
649
- *
650
- * @access protected
651
- * @param string $tag_name
652
- * @param string $leading Whitespace
653
- * @param string $trailing Whitespace
654
- * @return string
655
- */
656
- protected function _renderComment($tag_name, $leading, $trailing) {
657
- if ($leading !== null && $trailing !== null) {
658
- if (strpos($leading, "\n") === false) {
659
- return '';
660
- }
661
- return $this->_stringHasR($leading, $trailing) ? "\r\n" : "\n";
662
- }
663
- return $leading . $trailing;
664
- }
665
-
666
- /**
667
- * Return the requested tag unescaped.
668
- *
669
- * @access protected
670
- * @param string $tag_name
671
- * @param string $leading Whitespace
672
- * @param string $trailing Whitespace
673
- * @return string
674
- */
675
- protected function _renderUnescaped($tag_name, $leading, $trailing) {
676
- $val = $this->_getVariable($tag_name);
677
-
678
- if ($this->_varIsCallable($val)) {
679
- $val = $this->_renderTemplate(call_user_func($val));
680
- }
681
-
682
- return $leading . $val . $trailing;
683
- }
684
-
685
- /**
686
- * Render the requested partial.
687
- *
688
- * @access protected
689
- * @param string $tag_name
690
- * @param string $leading Whitespace
691
- * @param string $trailing Whitespace
692
- * @return string
693
- */
694
- protected function _renderPartial($tag_name, $leading, $trailing) {
695
- $partial = $this->_getPartial($tag_name);
696
- if ($leading !== null && $trailing !== null) {
697
- $whitespace = trim($leading, "\r\n");
698
- $partial = preg_replace('/(\\r?\\n)(?!$)/s', "\\1" . $whitespace, $partial);
699
- }
700
-
701
- $view = clone($this);
702
-
703
- if ($leading !== null && $trailing !== null) {
704
- return $leading . $view->render($partial);
705
- } else {
706
- return $leading . $view->render($partial) . $trailing;
707
- }
708
- }
709
-
710
- /**
711
- * Change the Mustache tag delimiter. This method also replaces this object's current
712
- * tag RegEx with one using the new delimiters.
713
- *
714
- * @access protected
715
- * @param string $tag_name
716
- * @param string $leading Whitespace
717
- * @param string $trailing Whitespace
718
- * @return string
719
- */
720
- protected function _changeDelimiter($tag_name, $leading, $trailing) {
721
- list($otag, $ctag) = explode(' ', $tag_name);
722
- $this->_otag = $otag;
723
- $this->_ctag = $ctag;
724
-
725
- $this->_tagRegEx = $this->_prepareTagRegEx($this->_otag, $this->_ctag);
726
-
727
- if ($leading !== null && $trailing !== null) {
728
- if (strpos($leading, "\n") === false) {
729
- return '';
730
- }
731
- return $this->_stringHasR($leading, $trailing) ? "\r\n" : "\n";
732
- }
733
- return $leading . $trailing;
734
- }
735
-
736
- /**
737
- * Push a local context onto the stack.
738
- *
739
- * @access protected
740
- * @param array &$local_context
741
- * @return void
742
- */
743
- protected function _pushContext(&$local_context) {
744
- $new = array();
745
- $new[] =& $local_context;
746
- foreach (array_keys($this->_context) as $key) {
747
- $new[] =& $this->_context[$key];
748
- }
749
- $this->_context = $new;
750
- }
751
-
752
- /**
753
- * Remove the latest context from the stack.
754
- *
755
- * @access protected
756
- * @return void
757
- */
758
- protected function _popContext() {
759
- $new = array();
760
-
761
- $keys = array_keys($this->_context);
762
- array_shift($keys);
763
- foreach ($keys as $key) {
764
- $new[] =& $this->_context[$key];
765
- }
766
- $this->_context = $new;
767
- }
768
-
769
- /**
770
- * Get a variable from the context array.
771
- *
772
- * If the view is an array, returns the value with array key $tag_name.
773
- * If the view is an object, this will check for a public member variable
774
- * named $tag_name. If none is available, this method will execute and return
775
- * any class method named $tag_name. Failing all of the above, this method will
776
- * return an empty string.
777
- *
778
- * @access protected
779
- * @param string $tag_name
780
- * @throws MustacheException Unknown variable name.
781
- * @return string
782
- */
783
- protected function _getVariable($tag_name) {
784
- if ($tag_name === '.') {
785
- return $this->_context[0];
786
- } else if (strpos($tag_name, '.') !== false) {
787
- $chunks = explode('.', $tag_name);
788
- $first = array_shift($chunks);
789
-
790
- $ret = $this->_findVariableInContext($first, $this->_context);
791
- foreach ($chunks as $next) {
792
- // Slice off a chunk of context for dot notation traversal.
793
- $c = array($ret);
794
- $ret = $this->_findVariableInContext($next, $c);
795
- }
796
- return $ret;
797
- } else {
798
- return $this->_findVariableInContext($tag_name, $this->_context);
799
- }
800
- }
801
-
802
- /**
803
- * Get a variable from the context array. Internal helper used by getVariable() to abstract
804
- * variable traversal for dot notation.
805
- *
806
- * @access protected
807
- * @param string $tag_name
808
- * @param array $context
809
- * @throws MustacheException Unknown variable name.
810
- * @return string
811
- */
812
- protected function _findVariableInContext($tag_name, $context) {
813
- foreach ($context as $view) {
814
- if (is_object($view)) {
815
- if (method_exists($view, $tag_name)) {
816
- return $view->$tag_name();
817
- } else if (isset($view->$tag_name)) {
818
- return $view->$tag_name;
819
- }
820
- } else if (is_array($view) && array_key_exists($tag_name, $view)) {
821
- return $view[$tag_name];
822
- }
823
- }
824
-
825
- if ($this->_throwsException(MustacheException::UNKNOWN_VARIABLE)) {
826
- throw new MustacheException("Unknown variable: " . $tag_name, MustacheException::UNKNOWN_VARIABLE);
827
- } else {
828
- return '';
829
- }
830
- }
831
-
832
- /**
833
- * Retrieve the partial corresponding to the requested tag name.
834
- *
835
- * Silently fails (i.e. returns '') when the requested partial is not found.
836
- *
837
- * @access protected
838
- * @param string $tag_name
839
- * @throws MustacheException Unknown partial name.
840
- * @return string
841
- */
842
- protected function _getPartial($tag_name) {
843
- if ((is_array($this->_partials) || $this->_partials instanceof ArrayAccess) && isset($this->_partials[$tag_name])) {
844
- return $this->_partials[$tag_name];
845
- }
846
-
847
- if ($this->_throwsException(MustacheException::UNKNOWN_PARTIAL)) {
848
- throw new MustacheException('Unknown partial: ' . $tag_name, MustacheException::UNKNOWN_PARTIAL);
849
- } else {
850
- return '';
851
- }
852
- }
853
-
854
- /**
855
- * Check whether the given $var should be iterated (i.e. in a section context).
856
- *
857
- * @access protected
858
- * @param mixed $var
859
- * @return bool
860
- */
861
- protected function _varIsIterable($var) {
862
- return $var instanceof Traversable || (is_array($var) && !array_diff_key($var, array_keys(array_keys($var))));
863
- }
864
-
865
- /**
866
- * Higher order sections helper: tests whether the section $var is a valid callback.
867
- *
868
- * In Mustache.php, a variable is considered 'callable' if the variable is:
869
- *
870
- * 1. an anonymous function.
871
- * 2. an object and the name of a public function, i.e. `array($SomeObject, 'methodName')`
872
- * 3. a class name and the name of a public static function, i.e. `array('SomeClass', 'methodName')`
873
- *
874
- * @access protected
875
- * @param mixed $var
876
- * @return bool
877
- */
878
- protected function _varIsCallable($var) {
879
- return !is_string($var) && is_callable($var);
880
- }
881
- }
882
-
883
-
884
- /**
885
- * MustacheException class.
886
- *
887
- * @extends Exception
888
- */
889
- class MustacheException extends Exception {
890
-
891
- // An UNKNOWN_VARIABLE exception is thrown when a {{variable}} is not found
892
- // in the current context.
893
- const UNKNOWN_VARIABLE = 0;
894
-
895
- // An UNCLOSED_SECTION exception is thrown when a {{#section}} is not closed.
896
- const UNCLOSED_SECTION = 1;
897
-
898
- // An UNEXPECTED_CLOSE_SECTION exception is thrown when {{/section}} appears
899
- // without a corresponding {{#section}} or {{^section}}.
900
- const UNEXPECTED_CLOSE_SECTION = 2;
901
-
902
- // An UNKNOWN_PARTIAL exception is thrown whenever a {{>partial}} tag appears
903
- // with no associated partial.
904
- const UNKNOWN_PARTIAL = 3;
905
-
906
- // An UNKNOWN_PRAGMA exception is thrown whenever a {{%PRAGMA}} tag appears
907
- // which can't be handled by this Mustache instance.
908
- const UNKNOWN_PRAGMA = 4;
909
-
910
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mustache/MustacheLoader.php DELETED
@@ -1,85 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * A Mustache Partial filesystem loader.
5
- *
6
- * @author Justin Hileman {@link http://justinhileman.com}
7
- */
8
- class MustacheLoader implements ArrayAccess {
9
-
10
- protected $baseDir;
11
- protected $partialsCache = array();
12
- protected $extension;
13
-
14
- /**
15
- * MustacheLoader constructor.
16
- *
17
- * @access public
18
- * @param string $baseDir Base template directory.
19
- * @param string $extension File extension for Mustache files (default: 'mustache')
20
- * @return void
21
- */
22
- public function __construct($baseDir, $extension = 'mustache') {
23
- if (!is_dir($baseDir)) {
24
- throw new InvalidArgumentException('$baseDir must be a valid directory, ' . $baseDir . ' given.');
25
- }
26
-
27
- $this->baseDir = $baseDir;
28
- $this->extension = $extension;
29
- }
30
-
31
- /**
32
- * @param string $offset Name of partial
33
- * @return boolean
34
- */
35
- public function offsetExists($offset) {
36
- return (isset($this->partialsCache[$offset]) || file_exists($this->pathName($offset)));
37
- }
38
-
39
- /**
40
- * @throws InvalidArgumentException if the given partial doesn't exist
41
- * @param string $offset Name of partial
42
- * @return string Partial template contents
43
- */
44
- public function offsetGet($offset) {
45
- if (!$this->offsetExists($offset)) {
46
- throw new InvalidArgumentException('Partial does not exist: ' . $offset);
47
- }
48
-
49
- if (!isset($this->partialsCache[$offset])) {
50
- $this->partialsCache[$offset] = file_get_contents($this->pathName($offset));
51
- }
52
-
53
- return $this->partialsCache[$offset];
54
- }
55
-
56
- /**
57
- * MustacheLoader is an immutable filesystem loader. offsetSet throws a LogicException if called.
58
- *
59
- * @throws LogicException
60
- * @return void
61
- */
62
- public function offsetSet($offset, $value) {
63
- throw new LogicException('Unable to set offset: MustacheLoader is an immutable ArrayAccess object.');
64
- }
65
-
66
- /**
67
- * MustacheLoader is an immutable filesystem loader. offsetUnset throws a LogicException if called.
68
- *
69
- * @throws LogicException
70
- * @return void
71
- */
72
- public function offsetUnset($offset) {
73
- throw new LogicException('Unable to unset offset: MustacheLoader is an immutable ArrayAccess object.');
74
- }
75
-
76
- /**
77
- * An internal helper for generating path names.
78
- *
79
- * @param string $file Partial name
80
- * @return string File path
81
- */
82
- protected function pathName($file) {
83
- return $this->baseDir . '/' . $file . '.' . $this->extension;
84
- }
85
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mustache/README.markdown DELETED
@@ -1,98 +0,0 @@
1
- Mustache.php
2
- ============
3
-
4
- A [Mustache](http://defunkt.github.com/mustache/) implementation in PHP.
5
-
6
-
7
- Usage
8
- -----
9
-
10
- A quick example:
11
-
12
- ```php
13
- <?php
14
- include('Mustache.php');
15
- $m = new Mustache;
16
- echo $m->render('Hello {{planet}}', array('planet' => 'World!'));
17
- // "Hello World!"
18
- ```
19
-
20
-
21
- And a more in-depth example--this is the canonical Mustache template:
22
-
23
- ```
24
- Hello {{name}}
25
- You have just won ${{value}}!
26
- {{#in_ca}}
27
- Well, ${{taxed_value}}, after taxes.
28
- {{/in_ca}}
29
- ```
30
-
31
-
32
- Along with the associated Mustache class:
33
-
34
- ```php
35
- <?php
36
- class Chris extends Mustache {
37
- public $name = "Chris";
38
- public $value = 10000;
39
-
40
- public function taxed_value() {
41
- return $this->value - ($this->value * 0.4);
42
- }
43
-
44
- public $in_ca = true;
45
- }
46
- ```
47
-
48
-
49
- Render it like so:
50
-
51
- ```php
52
- <?php
53
- $chris = new Chris;
54
- echo $chris->render($template);
55
- ```
56
-
57
-
58
- Here's the same thing, a different way:
59
-
60
- Create a view object--which could also be an associative array, but those don't do functions quite as well:
61
-
62
- ```php
63
- <?php
64
- class Chris {
65
- public $name = "Chris";
66
- public $value = 10000;
67
-
68
- public function taxed_value() {
69
- return $this->value - ($this->value * 0.4);
70
- }
71
-
72
- public $in_ca = true;
73
- }
74
- ```
75
-
76
-
77
- And render it:
78
-
79
- ```php
80
- <?php
81
- $chris = new Chris;
82
- $m = new Mustache;
83
- echo $m->render($template, $chris);
84
- ```
85
-
86
-
87
- Known Issues
88
- ------------
89
-
90
- * As of Mustache spec v1.1.2, there are a couple of whitespace bugs around section tags... Despite these failing tests, this
91
- version is actually *closer* to correct than previous releases.
92
-
93
-
94
- See Also
95
- --------
96
-
97
- * [Readme for the Ruby Mustache implementation](http://github.com/defunkt/mustache/blob/master/README.md).
98
- * [mustache(1)](http://mustache.github.com/mustache.1.html) and [mustache(5)](http://mustache.github.com/mustache.5.html) man pages.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
posts-to-posts.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: Posts 2 Posts
4
  Description: Create many-to-many relationships between all types of posts.
5
- Version: 1.6.3
6
  Author: scribu
7
  Author URI: http://scribu.net/
8
  Plugin URI: http://scribu.net/wordpress/posts-to-posts
@@ -10,32 +10,38 @@ Text Domain: posts-to-posts
10
  Domain Path: /lang
11
  */
12
 
13
- define( 'P2P_PLUGIN_VERSION', '1.6.3' );
14
 
15
  define( 'P2P_TEXTDOMAIN', 'posts-to-posts' );
16
 
17
- require_once dirname( __FILE__ ) . '/scb/load.php';
18
-
19
  function _p2p_load() {
20
  load_plugin_textdomain( P2P_TEXTDOMAIN, '', basename( dirname( __FILE__ ) ) . '/lang' );
21
 
22
- // Prevent activation issues if a bundled version of P2P core is already loaded.
23
- if ( function_exists( 'p2p_register_connection_type' ) ) {
24
- return;
25
  }
26
 
27
- require_once dirname( __FILE__ ) . '/core/init.php';
 
 
 
 
 
 
 
 
28
 
29
  register_uninstall_hook( __FILE__, array( 'P2P_Storage', 'uninstall' ) );
30
 
31
  if ( is_admin() )
32
  _p2p_load_admin();
33
  }
34
- scb_init( '_p2p_load' );
35
 
36
  function _p2p_load_admin() {
37
  P2P_Autoload::register( 'P2P_', dirname( __FILE__ ) . '/admin' );
38
 
 
 
39
  new P2P_Box_Factory;
40
  new P2P_Column_Factory;
41
  new P2P_Dropdown_Factory;
@@ -47,5 +53,16 @@ function _p2p_init() {
47
  // Safe hook for calling p2p_register_connection_type()
48
  do_action( 'p2p_init' );
49
  }
 
 
 
 
 
 
 
 
 
 
 
50
  add_action( 'wp_loaded', '_p2p_init' );
51
 
2
  /*
3
  Plugin Name: Posts 2 Posts
4
  Description: Create many-to-many relationships between all types of posts.
5
+ Version: 1.6.4
6
  Author: scribu
7
  Author URI: http://scribu.net/
8
  Plugin URI: http://scribu.net/wordpress/posts-to-posts
10
  Domain Path: /lang
11
  */
12
 
13
+ define( 'P2P_PLUGIN_VERSION', '1.6.4' );
14
 
15
  define( 'P2P_TEXTDOMAIN', 'posts-to-posts' );
16
 
 
 
17
  function _p2p_load() {
18
  load_plugin_textdomain( P2P_TEXTDOMAIN, '', basename( dirname( __FILE__ ) ) . '/lang' );
19
 
20
+ if ( !function_exists( 'p2p_register_connection_type' ) ) {
21
+ require_once dirname( __FILE__ ) . '/vendor/scribu/lib-posts-to-posts/autoload.php';
 
22
  }
23
 
24
+ P2P_Storage::init();
25
+
26
+ P2P_Query_Post::init();
27
+ P2P_Query_User::init();
28
+
29
+ P2P_URL_Query::init();
30
+
31
+ P2P_Widget::init();
32
+ P2P_Shortcodes::init();
33
 
34
  register_uninstall_hook( __FILE__, array( 'P2P_Storage', 'uninstall' ) );
35
 
36
  if ( is_admin() )
37
  _p2p_load_admin();
38
  }
 
39
 
40
  function _p2p_load_admin() {
41
  P2P_Autoload::register( 'P2P_', dirname( __FILE__ ) . '/admin' );
42
 
43
+ P2P_Mustache::init();
44
+
45
  new P2P_Box_Factory;
46
  new P2P_Column_Factory;
47
  new P2P_Dropdown_Factory;
53
  // Safe hook for calling p2p_register_connection_type()
54
  do_action( 'p2p_init' );
55
  }
56
+
57
+ if ( is_dir( dirname( __FILE__ ) . '/vendor' ) ) {
58
+ // Not using vendor/autload.php because scb-framework/load.php has better compatibility
59
+
60
+ require_once dirname( __FILE__ ) . '/vendor/mustache/mustache/src/Mustache/Autoloader.php';
61
+ Mustache_Autoloader::register();
62
+
63
+ require_once dirname( __FILE__ ) . '/vendor/scribu/scb-framework/load.php';
64
+ }
65
+
66
+ scb_init( '_p2p_load' );
67
  add_action( 'wp_loaded', '_p2p_init' );
68
 
readme.txt CHANGED
@@ -3,8 +3,8 @@
3
  Contributors: scribu, ciobi
4
  Tags: connections, custom post types, relationships, many-to-many, users
5
  Requires at least: 3.5
6
- Tested up to: 3.9
7
- Stable tag: 1.6.3
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -57,6 +57,12 @@ Additional info can be found on the [wiki](http://github.com/scribu/wp-posts-to-
57
 
58
  == Changelog ==
59
 
 
 
 
 
 
 
60
  = 1.6.3 =
61
  * added Serbian translation. props Borisa Djuraskovic
62
  * fixed spinner in admin box. props yamablam
3
  Contributors: scribu, ciobi
4
  Tags: connections, custom post types, relationships, many-to-many, users
5
  Requires at least: 3.5
6
+ Tested up to: 4.2
7
+ Stable tag: 1.6.4
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
57
 
58
  == Changelog ==
59
 
60
+ = 1.6.4 =
61
+ * added Danish translation. props phh
62
+ * updated Swedish translation. props EyesX
63
+ * fixed issue with multiple `parse_query` calls. props hezachenary
64
+ * added `p2p_post_admin_column_link` and `p2p_user_admin_column_link` filters. props PareshRadadiya
65
+
66
  = 1.6.3 =
67
  * added Serbian translation. props Borisa Djuraskovic
68
  * fixed spinner in admin box. props yamablam
vendor/mustache/mustache/.travis.yml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ language: php
2
+ php:
3
+ - 5.2
4
+ - 5.3
5
+ - 5.4
6
+ - 5.5
7
+ - 5.6
8
+ - hhvm
9
+
10
+ matrix:
11
+ allow_failures:
12
+ - php: hhvm # See https://github.com/facebook/hhvm/pull/1860
vendor/mustache/mustache/CONTRIBUTING.md ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributions welcome!
2
+
3
+
4
+ ### Here's a quick guide:
5
+
6
+ 1. [Fork the repo on GitHub](https://github.com/bobthecow/mustache.php).
7
+
8
+ 2. Run the test suite. We only take pull requests with passing tests, and it's great to know that you have a clean slate. Make sure you have PHPUnit 3.5+, then run `phpunit` from the project directory.
9
+
10
+ 3. Add tests for your change. Only refactoring and documentation changes require no new tests. If you are adding functionality or fixing a bug, add a test!
11
+
12
+ 4. Make the tests pass.
13
+
14
+ 5. Push your fork to GitHub and submit a pull request against the `dev` branch.
15
+
16
+
17
+ ### You can do some things to increase the chance that your pull request is accepted the first time:
18
+
19
+ * Submit one pull request per fix or feature.
20
+ * To help with that, do all your work in a feature branch (e.g. `feature/my-alsome-feature`).
21
+ * Follow the conventions you see used in the project.
22
+ * Use `phpcs --standard=PSR2` to check your changes against the coding standard.
23
+ * Write tests that fail without your code, and pass with it.
24
+ * Don't bump version numbers. Those will be updated — per [semver](http://semver.org) — once your change is merged into `master`.
25
+ * Update any documentation: docblocks, README, examples, etc.
26
+ * ... Don't update the wiki until your change is merged and released, but make a note in your pull request so we don't forget.
27
+
28
+
29
+ ### Mustache.php follows the PSR-* coding standards:
30
+
31
+ * [PSR-0: Class and file naming conventions](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md)
32
+ * [PSR-1: Basic coding standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md)
33
+ * [PSR-2: Coding style guide](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
vendor/mustache/mustache/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2010-2014 Justin Hileman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
19
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21
+ OR OTHER DEALINGS IN THE SOFTWARE.
vendor/mustache/mustache/README.md ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Mustache.php
2
+ ============
3
+
4
+ A [Mustache](http://mustache.github.com/) implementation in PHP.
5
+
6
+ [![Package version](http://img.shields.io/packagist/v/mustache/mustache.svg)](https://packagist.org/packages/mustache/mustache)
7
+ [![Build status](http://img.shields.io/travis/bobthecow/mustache.php/dev.svg)](http://travis-ci.org/bobthecow/mustache.php)
8
+ [![Monthly downloads](http://img.shields.io/packagist/dm/mustache/mustache.svg)](https://packagist.org/packages/mustache/mustache)
9
+
10
+
11
+ Usage
12
+ -----
13
+
14
+ A quick example:
15
+
16
+ ```php
17
+ <?php
18
+ $m = new Mustache_Engine;
19
+ echo $m->render('Hello {{planet}}', array('planet' => 'World!')); // "Hello World!"
20
+ ```
21
+
22
+
23
+ And a more in-depth example -- this is the canonical Mustache template:
24
+
25
+ ```html+jinja
26
+ Hello {{name}}
27
+ You have just won ${{value}}!
28
+ {{#in_ca}}
29
+ Well, ${{taxed_value}}, after taxes.
30
+ {{/in_ca}}
31
+ ```
32
+
33
+
34
+ Create a view "context" object -- which could also be an associative array, but those don't do functions quite as well:
35
+
36
+ ```php
37
+ <?php
38
+ class Chris {
39
+ public $name = "Chris";
40
+ public $value = 10000;
41
+
42
+ public function taxed_value() {
43
+ return $this->value - ($this->value * 0.4);
44
+ }
45
+
46
+ public $in_ca = true;
47
+ }
48
+ ```
49
+
50
+
51
+ And render it:
52
+
53
+ ```php
54
+ <?php
55
+ $m = new Mustache_Engine;
56
+ $chris = new Chris;
57
+ echo $m->render($template, $chris);
58
+ ```
59
+
60
+
61
+ And That's Not All!
62
+ -------------------
63
+
64
+ Read [the Mustache.php documentation](https://github.com/bobthecow/mustache.php/wiki/Home) for more information.
65
+
66
+
67
+ See Also
68
+ --------
69
+
70
+ * [Readme for the Ruby Mustache implementation](http://github.com/defunkt/mustache/blob/master/README.md).
71
+ * [mustache(5)](http://mustache.github.com/mustache.5.html) man page.
vendor/mustache/mustache/composer.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "mustache/mustache",
3
+ "description": "A Mustache implementation in PHP.",
4
+ "keywords": ["templating", "mustache"],
5
+ "homepage": "https://github.com/bobthecow/mustache.php",
6
+ "type": "library",
7
+ "license": "MIT",
8
+ "authors": [
9
+ {
10
+ "name": "Justin Hileman",
11
+ "email": "justin@justinhileman.info",
12
+ "homepage": "http://justinhileman.com"
13
+ }
14
+ ],
15
+ "require": {
16
+ "php": ">=5.2.4"
17
+ },
18
+ "require-dev": {
19
+ "phpunit/phpunit": "*"
20
+ },
21
+ "autoload": {
22
+ "psr-0": { "Mustache": "src/" }
23
+ }
24
+ }
vendor/mustache/mustache/phpunit.xml.dist ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <phpunit backupGlobals="false" colors="true" bootstrap="./test/bootstrap.php">
3
+ <testsuite name="Mustache">
4
+ <directory suffix="Test.php">./test</directory>
5
+ <exclude>./test/Mustache/Test/FiveThree</exclude>
6
+ </testsuite>
7
+
8
+ <testsuite name="Mustache FiveThree">
9
+ <directory suffix="Test.php" phpVersion="5.3.0" phpVersionOperator=">=">./test/Mustache/Test/FiveThree</directory>
10
+ </testsuite>
11
+
12
+ <filter>
13
+ <whitelist>
14
+ <directory suffix=".php">./src/Mustache</directory>
15
+ </whitelist>
16
+ </filter>
17
+ </phpunit>
vendor/mustache/mustache/src/Mustache/Autoloader.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Mustache class autoloader.
14
+ */
15
+ class Mustache_Autoloader
16
+ {
17
+ private $baseDir;
18
+
19
+ /**
20
+ * Autoloader constructor.
21
+ *
22
+ * @param string $baseDir Mustache library base directory (default: dirname(__FILE__).'/..')
23
+ */
24
+ public function __construct($baseDir = null)
25
+ {
26
+ if ($baseDir === null) {
27
+ $baseDir = dirname(__FILE__).'/..';
28
+ }
29
+
30
+ // realpath doesn't always work, for example, with stream URIs
31
+ $realDir = realpath($baseDir);
32
+ if (is_dir($realDir)) {
33
+ $this->baseDir = $realDir;
34
+ } else {
35
+ $this->baseDir = $baseDir;
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Register a new instance as an SPL autoloader.
41
+ *
42
+ * @param string $baseDir Mustache library base directory (default: dirname(__FILE__).'/..')
43
+ *
44
+ * @return Mustache_Autoloader Registered Autoloader instance
45
+ */
46
+ public static function register($baseDir = null)
47
+ {
48
+ $loader = new self($baseDir);
49
+ spl_autoload_register(array($loader, 'autoload'));
50
+
51
+ return $loader;
52
+ }
53
+
54
+ /**
55
+ * Autoload Mustache classes.
56
+ *
57
+ * @param string $class
58
+ */
59
+ public function autoload($class)
60
+ {
61
+ if ($class[0] === '\\') {
62
+ $class = substr($class, 1);
63
+ }
64
+
65
+ if (strpos($class, 'Mustache') !== 0) {
66
+ return;
67
+ }
68
+
69
+ $file = sprintf('%s/%s.php', $this->baseDir, str_replace('_', '/', $class));
70
+ if (is_file($file)) {
71
+ require $file;
72
+ }
73
+ }
74
+ }
vendor/mustache/mustache/src/Mustache/Cache.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Mustache Cache interface.
14
+ *
15
+ * Interface for caching and loading Mustache_Template classes
16
+ * generated by the Mustache_Compiler.
17
+ */
18
+ interface Mustache_Cache
19
+ {
20
+ /**
21
+ * Load a compiled Mustache_Template class from cache.
22
+ *
23
+ * @param string $key
24
+ *
25
+ * @return boolean indicates successfully class load
26
+ */
27
+ public function load($key);
28
+
29
+ /**
30
+ * Cache and load a compiled Mustache_Template class.
31
+ *
32
+ * @param string $key
33
+ * @param string $value
34
+ *
35
+ * @return void
36
+ */
37
+ public function cache($key, $value);
38
+ }
vendor/mustache/mustache/src/Mustache/Cache/AbstractCache.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Abstract Mustache Cache class.
14
+ *
15
+ * Provides logging support to child implementations.
16
+ *
17
+ * @abstract
18
+ */
19
+ abstract class Mustache_Cache_AbstractCache implements Mustache_Cache
20
+ {
21
+ private $logger = null;
22
+
23
+ /**
24
+ * Get the current logger instance.
25
+ *
26
+ * @return Mustache_Logger|Psr\Log\LoggerInterface
27
+ */
28
+ public function getLogger()
29
+ {
30
+ return $this->logger;
31
+ }
32
+
33
+ /**
34
+ * Set a logger instance.
35
+ *
36
+ * @param Mustache_Logger|Psr\Log\LoggerInterface $logger
37
+ */
38
+ public function setLogger($logger = null)
39
+ {
40
+ if ($logger !== null && !($logger instanceof Mustache_Logger || is_a($logger, 'Psr\\Log\\LoggerInterface'))) {
41
+ throw new Mustache_Exception_InvalidArgumentException('Expected an instance of Mustache_Logger or Psr\\Log\\LoggerInterface.');
42
+ }
43
+
44
+ $this->logger = $logger;
45
+ }
46
+
47
+ /**
48
+ * Add a log record if logging is enabled.
49
+ *
50
+ * @param integer $level The logging level
51
+ * @param string $message The log message
52
+ * @param array $context The log context
53
+ */
54
+ protected function log($level, $message, array $context = array())
55
+ {
56
+ if (isset($this->logger)) {
57
+ $this->logger->log($level, $message, $context);
58
+ }
59
+ }
60
+ }
vendor/mustache/mustache/src/Mustache/Cache/FilesystemCache.php ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Mustache Cache filesystem implementation.
14
+ *
15
+ * A FilesystemCache instance caches Mustache Template classes from the filesystem by name:
16
+ *
17
+ * $cache = new Mustache_Cache_FilesystemCache(dirname(__FILE__).'/cache');
18
+ * $cache->cache($className, $compiledSource);
19
+ *
20
+ * The FilesystemCache benefits from any opcode caching that may be setup in your environment. So do that, k?
21
+ */
22
+ class Mustache_Cache_FilesystemCache extends Mustache_Cache_AbstractCache
23
+ {
24
+ private $baseDir;
25
+ private $fileMode;
26
+
27
+ /**
28
+ * Filesystem cache constructor.
29
+ *
30
+ * @param string $baseDir Directory for compiled templates.
31
+ * @param int $fileMode Override default permissions for cache files. Defaults to using the system-defined umask.
32
+ */
33
+ public function __construct($baseDir, $fileMode = null)
34
+ {
35
+ $this->baseDir = $baseDir;
36
+ $this->fileMode = $fileMode;
37
+ }
38
+
39
+ /**
40
+ * Load the class from cache using `require_once`.
41
+ *
42
+ * @param string $key
43
+ *
44
+ * @return boolean
45
+ */
46
+ public function load($key)
47
+ {
48
+ $fileName = $this->getCacheFilename($key);
49
+ if (!is_file($fileName)) {
50
+ return false;
51
+ }
52
+
53
+ require_once $fileName;
54
+
55
+ return true;
56
+ }
57
+
58
+ /**
59
+ * Cache and load the compiled class
60
+ *
61
+ * @param string $key
62
+ * @param string $value
63
+ *
64
+ * @return void
65
+ */
66
+ public function cache($key, $value)
67
+ {
68
+ $fileName = $this->getCacheFilename($key);
69
+
70
+ $this->log(
71
+ Mustache_Logger::DEBUG,
72
+ 'Writing to template cache: "{fileName}"',
73
+ array('fileName' => $fileName)
74
+ );
75
+
76
+ $this->writeFile($fileName, $value);
77
+ $this->load($key);
78
+ }
79
+
80
+ /**
81
+ * Build the cache filename.
82
+ * Subclasses should override for custom cache directory structures.
83
+ *
84
+ * @param string $name
85
+ *
86
+ * @return string
87
+ */
88
+ protected function getCacheFilename($name)
89
+ {
90
+ return sprintf('%s/%s.php', $this->baseDir, $name);
91
+ }
92
+
93
+ /**
94
+ * Create cache directory
95
+ *
96
+ * @throws Mustache_Exception_RuntimeException If unable to create directory
97
+ *
98
+ * @param string $fileName
99
+ *
100
+ * @return string
101
+ */
102
+ private function buildDirectoryForFilename($fileName)
103
+ {
104
+ $dirName = dirname($fileName);
105
+ if (!is_dir($dirName)) {
106
+ $this->log(
107
+ Mustache_Logger::INFO,
108
+ 'Creating Mustache template cache directory: "{dirName}"',
109
+ array('dirName' => $dirName)
110
+ );
111
+
112
+ @mkdir($dirName, 0777, true);
113
+ if (!is_dir($dirName)) {
114
+ throw new Mustache_Exception_RuntimeException(sprintf('Failed to create cache directory "%s".', $dirName));
115
+ }
116
+ }
117
+
118
+ return $dirName;
119
+ }
120
+
121
+ /**
122
+ * Write cache file
123
+ *
124
+ * @throws Mustache_Exception_RuntimeException If unable to write file
125
+ *
126
+ * @param string $fileName
127
+ * @param string $value
128
+ *
129
+ * @return void
130
+ */
131
+ private function writeFile($fileName, $value)
132
+ {
133
+ $dirName = $this->buildDirectoryForFilename($fileName);
134
+
135
+ $this->log(
136
+ Mustache_Logger::DEBUG,
137
+ 'Caching compiled template to "{fileName}"',
138
+ array('fileName' => $fileName)
139
+ );
140
+
141
+ $tempFile = tempnam($dirName, basename($fileName));
142
+ if (false !== @file_put_contents($tempFile, $value)) {
143
+ if (@rename($tempFile, $fileName)) {
144
+ $mode = isset($this->fileMode) ? $this->fileMode : (0666 & ~umask());
145
+ @chmod($fileName, $mode);
146
+
147
+ return;
148
+ }
149
+
150
+ $this->log(
151
+ Mustache_Logger::ERROR,
152
+ 'Unable to rename Mustache temp cache file: "{tempName}" -> "{fileName}"',
153
+ array('tempName' => $tempFile, 'fileName' => $fileName)
154
+ );
155
+ }
156
+
157
+ throw new Mustache_Exception_RuntimeException(sprintf('Failed to write cache file "%s".', $fileName));
158
+ }
159
+ }
vendor/mustache/mustache/src/Mustache/Cache/NoopCache.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Mustache Cache in-memory implementation.
14
+ *
15
+ * The in-memory cache is used for uncached lambda section templates. It's also useful during development, but is not
16
+ * recommended for production use.
17
+ */
18
+ class Mustache_Cache_NoopCache extends Mustache_Cache_AbstractCache
19
+ {
20
+ /**
21
+ * Loads nothing. Move along.
22
+ *
23
+ * @param string $key
24
+ *
25
+ * @return boolean
26
+ */
27
+ public function load($key)
28
+ {
29
+ return false;
30
+ }
31
+
32
+ /**
33
+ * Loads the compiled Mustache Template class without caching.
34
+ *
35
+ * @param string $key
36
+ * @param string $value
37
+ *
38
+ * @return void
39
+ */
40
+ public function cache($key, $value)
41
+ {
42
+ $this->log(
43
+ Mustache_Logger::WARNING,
44
+ 'Template cache disabled, evaluating "{className}" class at runtime',
45
+ array('className' => $key)
46
+ );
47
+ eval('?>' . $value);
48
+ }
49
+ }
vendor/mustache/mustache/src/Mustache/Compiler.php ADDED
@@ -0,0 +1,493 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Mustache Compiler class.
14
+ *
15
+ * This class is responsible for turning a Mustache token parse tree into normal PHP source code.
16
+ */
17
+ class Mustache_Compiler
18
+ {
19
+ private $sections;
20
+ private $source;
21
+ private $indentNextLine;
22
+ private $customEscape;
23
+ private $entityFlags;
24
+ private $charset;
25
+ private $strictCallables;
26
+ private $pragmas;
27
+
28
+ /**
29
+ * Compile a Mustache token parse tree into PHP source code.
30
+ *
31
+ * @param string $source Mustache Template source code
32
+ * @param string $tree Parse tree of Mustache tokens
33
+ * @param string $name Mustache Template class name
34
+ * @param bool $customEscape (default: false)
35
+ * @param string $charset (default: 'UTF-8')
36
+ * @param bool $strictCallables (default: false)
37
+ * @param int $entityFlags (default: ENT_COMPAT)
38
+ *
39
+ * @return string Generated PHP source code
40
+ */
41
+ public function compile($source, array $tree, $name, $customEscape = false, $charset = 'UTF-8', $strictCallables = false, $entityFlags = ENT_COMPAT)
42
+ {
43
+ $this->pragmas = array();
44
+ $this->sections = array();
45
+ $this->source = $source;
46
+ $this->indentNextLine = true;
47
+ $this->customEscape = $customEscape;
48
+ $this->entityFlags = $entityFlags;
49
+ $this->charset = $charset;
50
+ $this->strictCallables = $strictCallables;
51
+
52
+ return $this->writeCode($tree, $name);
53
+ }
54
+
55
+ /**
56
+ * Helper function for walking the Mustache token parse tree.
57
+ *
58
+ * @throws Mustache_Exception_SyntaxException upon encountering unknown token types.
59
+ *
60
+ * @param array $tree Parse tree of Mustache tokens
61
+ * @param int $level (default: 0)
62
+ *
63
+ * @return string Generated PHP source code
64
+ */
65
+ private function walk(array $tree, $level = 0)
66
+ {
67
+ $code = '';
68
+ $level++;
69
+ foreach ($tree as $node) {
70
+ switch ($node[Mustache_Tokenizer::TYPE]) {
71
+ case Mustache_Tokenizer::T_PRAGMA:
72
+ $this->pragmas[$node[Mustache_Tokenizer::NAME]] = true;
73
+ break;
74
+
75
+ case Mustache_Tokenizer::T_SECTION:
76
+ $code .= $this->section(
77
+ $node[Mustache_Tokenizer::NODES],
78
+ $node[Mustache_Tokenizer::NAME],
79
+ $node[Mustache_Tokenizer::INDEX],
80
+ $node[Mustache_Tokenizer::END],
81
+ $node[Mustache_Tokenizer::OTAG],
82
+ $node[Mustache_Tokenizer::CTAG],
83
+ $level
84
+ );
85
+ break;
86
+
87
+ case Mustache_Tokenizer::T_INVERTED:
88
+ $code .= $this->invertedSection(
89
+ $node[Mustache_Tokenizer::NODES],
90
+ $node[Mustache_Tokenizer::NAME],
91
+ $level
92
+ );
93
+ break;
94
+
95
+ case Mustache_Tokenizer::T_PARTIAL:
96
+ case Mustache_Tokenizer::T_PARTIAL_2:
97
+ $code .= $this->partial(
98
+ $node[Mustache_Tokenizer::NAME],
99
+ isset($node[Mustache_Tokenizer::INDENT]) ? $node[Mustache_Tokenizer::INDENT] : '',
100
+ $level
101
+ );
102
+ break;
103
+
104
+ case Mustache_Tokenizer::T_UNESCAPED:
105
+ case Mustache_Tokenizer::T_UNESCAPED_2:
106
+ $code .= $this->variable($node[Mustache_Tokenizer::NAME], false, $level);
107
+ break;
108
+
109
+ case Mustache_Tokenizer::T_COMMENT:
110
+ break;
111
+
112
+ case Mustache_Tokenizer::T_ESCAPED:
113
+ $code .= $this->variable($node[Mustache_Tokenizer::NAME], true, $level);
114
+ break;
115
+
116
+ case Mustache_Tokenizer::T_TEXT:
117
+ $code .= $this->text($node[Mustache_Tokenizer::VALUE], $level);
118
+ break;
119
+
120
+ default:
121
+ throw new Mustache_Exception_SyntaxException(sprintf('Unknown token type: %s', $node[Mustache_Tokenizer::TYPE]), $node);
122
+ }
123
+ }
124
+
125
+ return $code;
126
+ }
127
+
128
+ const KLASS = '<?php
129
+
130
+ class %s extends Mustache_Template
131
+ {
132
+ private $lambdaHelper;%s
133
+
134
+ public function renderInternal(Mustache_Context $context, $indent = \'\')
135
+ {
136
+ $this->lambdaHelper = new Mustache_LambdaHelper($this->mustache, $context);
137
+ $buffer = \'\';
138
+ %s
139
+
140
+ return $buffer;
141
+ }
142
+ %s
143
+ }';
144
+
145
+ const KLASS_NO_LAMBDAS = '<?php
146
+
147
+ class %s extends Mustache_Template
148
+ {%s
149
+ public function renderInternal(Mustache_Context $context, $indent = \'\')
150
+ {
151
+ $buffer = \'\';
152
+ %s
153
+
154
+ return $buffer;
155
+ }
156
+ }';
157
+
158
+ const STRICT_CALLABLE = 'protected $strictCallables = true;';
159
+
160
+ /**
161
+ * Generate Mustache Template class PHP source.
162
+ *
163
+ * @param array $tree Parse tree of Mustache tokens
164
+ * @param string $name Mustache Template class name
165
+ *
166
+ * @return string Generated PHP source code
167
+ */
168
+ private function writeCode($tree, $name)
169
+ {
170
+ $code = $this->walk($tree);
171
+ $sections = implode("\n", $this->sections);
172
+ $klass = empty($this->sections) ? self::KLASS_NO_LAMBDAS : self::KLASS;
173
+ $callable = $this->strictCallables ? $this->prepare(self::STRICT_CALLABLE) : '';
174
+
175
+ return sprintf($this->prepare($klass, 0, false, true), $name, $callable, $code, $sections);
176
+ }
177
+
178
+ const SECTION_CALL = '
179
+ // %s section
180
+ $value = $context->%s(%s);%s
181
+ $buffer .= $this->section%s($context, $indent, $value);
182
+ ';
183
+
184
+ const SECTION = '
185
+ private function section%s(Mustache_Context $context, $indent, $value)
186
+ {
187
+ $buffer = \'\';
188
+ if (%s) {
189
+ $source = %s;
190
+ $result = call_user_func($value, $source, $this->lambdaHelper);
191
+ if (strpos($result, \'{{\') === false) {
192
+ $buffer .= $result;
193
+ } else {
194
+ $buffer .= $this->mustache
195
+ ->loadLambda((string) $result%s)
196
+ ->renderInternal($context);
197
+ }
198
+ } elseif (!empty($value)) {
199
+ $values = $this->isIterable($value) ? $value : array($value);
200
+ foreach ($values as $value) {
201
+ $context->push($value);%s
202
+ $context->pop();
203
+ }
204
+ }
205
+
206
+ return $buffer;
207
+ }';
208
+
209
+ /**
210
+ * Generate Mustache Template section PHP source.
211
+ *
212
+ * @param array $nodes Array of child tokens
213
+ * @param string $id Section name
214
+ * @param int $start Section start offset
215
+ * @param int $end Section end offset
216
+ * @param string $otag Current Mustache opening tag
217
+ * @param string $ctag Current Mustache closing tag
218
+ * @param int $level
219
+ *
220
+ * @return string Generated section PHP source code
221
+ */
222
+ private function section($nodes, $id, $start, $end, $otag, $ctag, $level)
223
+ {
224
+ $filters = '';
225
+
226
+ if (isset($this->pragmas[Mustache_Engine::PRAGMA_FILTERS])) {
227
+ list($id, $filters) = $this->getFilters($id, $level);
228
+ }
229
+
230
+ $method = $this->getFindMethod($id);
231
+ $id = var_export($id, true);
232
+ $source = var_export(substr($this->source, $start, $end - $start), true);
233
+ $callable = $this->getCallable();
234
+
235
+ if ($otag !== '{{' || $ctag !== '}}') {
236
+ $delims = ', '.var_export(sprintf('{{= %s %s =}}', $otag, $ctag), true);
237
+ } else {
238
+ $delims = '';
239
+ }
240
+
241
+ $key = ucfirst(md5($delims."\n".$source));
242
+
243
+ if (!isset($this->sections[$key])) {
244
+ $this->sections[$key] = sprintf($this->prepare(self::SECTION), $key, $callable, $source, $delims, $this->walk($nodes, 2));
245
+ }
246
+
247
+ return sprintf($this->prepare(self::SECTION_CALL, $level), $id, $method, $id, $filters, $key);
248
+ }
249
+
250
+ const INVERTED_SECTION = '
251
+ // %s inverted section
252
+ $value = $context->%s(%s);%s
253
+ if (empty($value)) {
254
+ %s
255
+ }';
256
+
257
+ /**
258
+ * Generate Mustache Template inverted section PHP source.
259
+ *
260
+ * @param array $nodes Array of child tokens
261
+ * @param string $id Section name
262
+ * @param int $level
263
+ *
264
+ * @return string Generated inverted section PHP source code
265
+ */
266
+ private function invertedSection($nodes, $id, $level)
267
+ {
268
+ $filters = '';
269
+
270
+ if (isset($this->pragmas[Mustache_Engine::PRAGMA_FILTERS])) {
271
+ list($id, $filters) = $this->getFilters($id, $level);
272
+ }
273
+
274
+ $method = $this->getFindMethod($id);
275
+ $id = var_export($id, true);
276
+
277
+ return sprintf($this->prepare(self::INVERTED_SECTION, $level), $id, $method, $id, $filters, $this->walk($nodes, $level));
278
+ }
279
+
280
+ const PARTIAL = '
281
+ if ($partial = $this->mustache->loadPartial(%s)) {
282
+ $buffer .= $partial->renderInternal($context, $indent . %s);
283
+ }
284
+ ';
285
+
286
+ /**
287
+ * Generate Mustache Template partial call PHP source.
288
+ *
289
+ * @param string $id Partial name
290
+ * @param string $indent Whitespace indent to apply to partial
291
+ * @param int $level
292
+ *
293
+ * @return string Generated partial call PHP source code
294
+ */
295
+ private function partial($id, $indent, $level)
296
+ {
297
+ return sprintf(
298
+ $this->prepare(self::PARTIAL, $level),
299
+ var_export($id, true),
300
+ var_export($indent, true)
301
+ );
302
+ }
303
+
304
+ const VARIABLE = '
305
+ $value = $this->resolveValue($context->%s(%s), $context, $indent);%s
306
+ $buffer .= %s%s;
307
+ ';
308
+
309
+ /**
310
+ * Generate Mustache Template variable interpolation PHP source.
311
+ *
312
+ * @param string $id Variable name
313
+ * @param boolean $escape Escape the variable value for output?
314
+ * @param int $level
315
+ *
316
+ * @return string Generated variable interpolation PHP source
317
+ */
318
+ private function variable($id, $escape, $level)
319
+ {
320
+ $filters = '';
321
+
322
+ if (isset($this->pragmas[Mustache_Engine::PRAGMA_FILTERS])) {
323
+ list($id, $filters) = $this->getFilters($id, $level);
324
+ }
325
+
326
+ $method = $this->getFindMethod($id);
327
+ $id = ($method !== 'last') ? var_export($id, true) : '';
328
+ $value = $escape ? $this->getEscape() : '$value';
329
+
330
+ return sprintf($this->prepare(self::VARIABLE, $level), $method, $id, $filters, $this->flushIndent(), $value);
331
+ }
332
+
333
+ /**
334
+ * Generate Mustache Template variable filtering PHP source.
335
+ *
336
+ * @param string $id Variable name
337
+ * @param int $level
338
+ *
339
+ * @return string Generated variable filtering PHP source
340
+ */
341
+ private function getFilters($id, $level)
342
+ {
343
+ $filters = array_map('trim', explode('|', $id));
344
+ $id = array_shift($filters);
345
+
346
+ return array($id, $this->getFilter($filters, $level));
347
+ }
348
+
349
+ const FILTER = '
350
+ $filter = $context->%s(%s);
351
+ if (!(%s)) {
352
+ throw new Mustache_Exception_UnknownFilterException(%s);
353
+ }
354
+ $value = call_user_func($filter, $value);%s
355
+ ';
356
+
357
+ /**
358
+ * Generate PHP source for a single filter.
359
+ *
360
+ * @param array $filters
361
+ * @param int $level
362
+ *
363
+ * @return string Generated filter PHP source
364
+ */
365
+ private function getFilter(array $filters, $level)
366
+ {
367
+ if (empty($filters)) {
368
+ return '';
369
+ }
370
+
371
+ $name = array_shift($filters);
372
+ $method = $this->getFindMethod($name);
373
+ $filter = ($method !== 'last') ? var_export($name, true) : '';
374
+ $callable = $this->getCallable('$filter');
375
+ $msg = var_export($name, true);
376
+
377
+ return sprintf($this->prepare(self::FILTER, $level), $method, $filter, $callable, $msg, $this->getFilter($filters, $level));
378
+ }
379
+
380
+ const LINE = '$buffer .= "\n";';
381
+ const TEXT = '$buffer .= %s%s;';
382
+
383
+ /**
384
+ * Generate Mustache Template output Buffer call PHP source.
385
+ *
386
+ * @param string $text
387
+ * @param int $level
388
+ *
389
+ * @return string Generated output Buffer call PHP source
390
+ */
391
+ private function text($text, $level)
392
+ {
393
+ $indentNextLine = (substr($text, -1) === "\n");
394
+ $code = sprintf($this->prepare(self::TEXT, $level), $this->flushIndent(), var_export($text, true));
395
+ $this->indentNextLine = $indentNextLine;
396
+
397
+ return $code;
398
+ }
399
+
400
+ /**
401
+ * Prepare PHP source code snippet for output.
402
+ *
403
+ * @param string $text
404
+ * @param int $bonus Additional indent level (default: 0)
405
+ * @param boolean $prependNewline Prepend a newline to the snippet? (default: true)
406
+ * @param boolean $appendNewline Append a newline to the snippet? (default: false)
407
+ *
408
+ * @return string PHP source code snippet
409
+ */
410
+ private function prepare($text, $bonus = 0, $prependNewline = true, $appendNewline = false)
411
+ {
412
+ $text = ($prependNewline ? "\n" : '').trim($text);
413
+ if ($prependNewline) {
414
+ $bonus++;
415
+ }
416
+ if ($appendNewline) {
417
+ $text .= "\n";
418
+ }
419
+
420
+ return preg_replace("/\n( {8})?/", "\n".str_repeat(" ", $bonus * 4), $text);
421
+ }
422
+
423
+ const DEFAULT_ESCAPE = 'htmlspecialchars(%s, %s, %s)';
424
+ const CUSTOM_ESCAPE = 'call_user_func($this->mustache->getEscape(), %s)';
425
+
426
+ /**
427
+ * Get the current escaper.
428
+ *
429
+ * @param string $value (default: '$value')
430
+ *
431
+ * @return string Either a custom callback, or an inline call to `htmlspecialchars`
432
+ */
433
+ private function getEscape($value = '$value')
434
+ {
435
+ if ($this->customEscape) {
436
+ return sprintf(self::CUSTOM_ESCAPE, $value);
437
+ } else {
438
+ return sprintf(self::DEFAULT_ESCAPE, $value, var_export($this->entityFlags, true), var_export($this->charset, true));
439
+ }
440
+ }
441
+
442
+ /**
443
+ * Select the appropriate Context `find` method for a given $id.
444
+ *
445
+ * The return value will be one of `find`, `findDot` or `last`.
446
+ *
447
+ * @see Mustache_Context::find
448
+ * @see Mustache_Context::findDot
449
+ * @see Mustache_Context::last
450
+ *
451
+ * @param string $id Variable name
452
+ *
453
+ * @return string `find` method name
454
+ */
455
+ private function getFindMethod($id)
456
+ {
457
+ if ($id === '.') {
458
+ return 'last';
459
+ } elseif (strpos($id, '.') === false) {
460
+ return 'find';
461
+ } else {
462
+ return 'findDot';
463
+ }
464
+ }
465
+
466
+ const IS_CALLABLE = '!is_string(%s) && is_callable(%s)';
467
+ const STRICT_IS_CALLABLE = 'is_object(%s) && is_callable(%s)';
468
+
469
+ private function getCallable($variable = '$value')
470
+ {
471
+ $tpl = $this->strictCallables ? self::STRICT_IS_CALLABLE : self::IS_CALLABLE;
472
+
473
+ return sprintf($tpl, $variable, $variable);
474
+ }
475
+
476
+ const LINE_INDENT = '$indent . ';
477
+
478
+ /**
479
+ * Get the current $indent prefix to write to the buffer.
480
+ *
481
+ * @return string "$indent . " or ""
482
+ */
483
+ private function flushIndent()
484
+ {
485
+ if (!$this->indentNextLine) {
486
+ return '';
487
+ }
488
+
489
+ $this->indentNextLine = false;
490
+
491
+ return self::LINE_INDENT;
492
+ }
493
+ }
vendor/mustache/mustache/src/Mustache/Context.php ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Mustache Template rendering Context.
14
+ */
15
+ class Mustache_Context
16
+ {
17
+ private $stack = array();
18
+
19
+ /**
20
+ * Mustache rendering Context constructor.
21
+ *
22
+ * @param mixed $context Default rendering context (default: null)
23
+ */
24
+ public function __construct($context = null)
25
+ {
26
+ if ($context !== null) {
27
+ $this->stack = array($context);
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Push a new Context frame onto the stack.
33
+ *
34
+ * @param mixed $value Object or array to use for context
35
+ */
36
+ public function push($value)
37
+ {
38
+ array_push($this->stack, $value);
39
+ }
40
+
41
+ /**
42
+ * Pop the last Context frame from the stack.
43
+ *
44
+ * @return mixed Last Context frame (object or array)
45
+ */
46
+ public function pop()
47
+ {
48
+ return array_pop($this->stack);
49
+ }
50
+
51
+ /**
52
+ * Get the last Context frame.
53
+ *
54
+ * @return mixed Last Context frame (object or array)
55
+ */
56
+ public function last()
57
+ {
58
+ return end($this->stack);
59
+ }
60
+
61
+ /**
62
+ * Find a variable in the Context stack.
63
+ *
64
+ * Starting with the last Context frame (the context of the innermost section), and working back to the top-level
65
+ * rendering context, look for a variable with the given name:
66
+ *
67
+ * * If the Context frame is an associative array which contains the key $id, returns the value of that element.
68
+ * * If the Context frame is an object, this will check first for a public method, then a public property named
69
+ * $id. Failing both of these, it will try `__isset` and `__get` magic methods.
70
+ * * If a value named $id is not found in any Context frame, returns an empty string.
71
+ *
72
+ * @param string $id Variable name
73
+ *
74
+ * @return mixed Variable value, or '' if not found
75
+ */
76
+ public function find($id)
77
+ {
78
+ return $this->findVariableInStack($id, $this->stack);
79
+ }
80
+
81
+ /**
82
+ * Find a 'dot notation' variable in the Context stack.
83
+ *
84
+ * Note that dot notation traversal bubbles through scope differently than the regular find method. After finding
85
+ * the initial chunk of the dotted name, each subsequent chunk is searched for only within the value of the previous
86
+ * result. For example, given the following context stack:
87
+ *
88
+ * $data = array(
89
+ * 'name' => 'Fred',
90
+ * 'child' => array(
91
+ * 'name' => 'Bob'
92
+ * ),
93
+ * );
94
+ *
95
+ * ... and the Mustache following template:
96
+ *
97
+ * {{ child.name }}
98
+ *
99
+ * ... the `name` value is only searched for within the `child` value of the global Context, not within parent
100
+ * Context frames.
101
+ *
102
+ * @param string $id Dotted variable selector
103
+ *
104
+ * @return mixed Variable value, or '' if not found
105
+ */
106
+ public function findDot($id)
107
+ {
108
+ $chunks = explode('.', $id);
109
+ $first = array_shift($chunks);
110
+ $value = $this->findVariableInStack($first, $this->stack);
111
+
112
+ foreach ($chunks as $chunk) {
113
+ if ($value === '') {
114
+ return $value;
115
+ }
116
+
117
+ $value = $this->findVariableInStack($chunk, array($value));
118
+ }
119
+
120
+ return $value;
121
+ }
122
+
123
+ /**
124
+ * Helper function to find a variable in the Context stack.
125
+ *
126
+ * @see Mustache_Context::find
127
+ *
128
+ * @param string $id Variable name
129
+ * @param array $stack Context stack
130
+ *
131
+ * @return mixed Variable value, or '' if not found
132
+ */
133
+ private function findVariableInStack($id, array $stack)
134
+ {
135
+ for ($i = count($stack) - 1; $i >= 0; $i--) {
136
+ if (is_object($stack[$i]) && !($stack[$i] instanceof Closure)) {
137
+
138
+ // Note that is_callable() *will not work here*
139
+ // See https://github.com/bobthecow/mustache.php/wiki/Magic-Methods
140
+ if (method_exists($stack[$i], $id)) {
141
+ return $stack[$i]->$id();
142
+ } elseif (isset($stack[$i]->$id)) {
143
+ return $stack[$i]->$id;
144
+ } elseif ($stack[$i] instanceof ArrayAccess && isset($stack[$i][$id])) {
145
+ return $stack[$i][$id];
146
+ }
147
+ } elseif (is_array($stack[$i]) && array_key_exists($id, $stack[$i])) {
148
+ return $stack[$i][$id];
149
+ }
150
+ }
151
+
152
+ return '';
153
+ }
154
+ }
vendor/mustache/mustache/src/Mustache/Engine.php ADDED
@@ -0,0 +1,747 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * A Mustache implementation in PHP.
14
+ *
15
+ * {@link http://defunkt.github.com/mustache}
16
+ *
17
+ * Mustache is a framework-agnostic logic-less templating language. It enforces separation of view
18
+ * logic from template files. In fact, it is not even possible to embed logic in the template.
19
+ *
20
+ * This is very, very rad.
21
+ *
22
+ * @author Justin Hileman {@link http://justinhileman.com}
23
+ */
24
+ class Mustache_Engine
25
+ {
26
+ const VERSION = '2.6.1';
27
+ const SPEC_VERSION = '1.1.2';
28
+
29
+ const PRAGMA_FILTERS = 'FILTERS';
30
+
31
+ // Template cache
32
+ private $templates = array();
33
+
34
+ // Environment
35
+ private $templateClassPrefix = '__Mustache_';
36
+ private $cache;
37
+ private $lambdaCache;
38
+ private $cacheLambdaTemplates = false;
39
+ private $loader;
40
+ private $partialsLoader;
41
+ private $helpers;
42
+ private $escape;
43
+ private $entityFlags = ENT_COMPAT;
44
+ private $charset = 'UTF-8';
45
+ private $logger;
46
+ private $strictCallables = false;
47
+
48
+ // Services
49
+ private $tokenizer;
50
+ private $parser;
51
+ private $compiler;
52
+
53
+ /**
54
+ * Mustache class constructor.
55
+ *
56
+ * Passing an $options array allows overriding certain Mustache options during instantiation:
57
+ *
58
+ * $options = array(
59
+ * // The class prefix for compiled templates. Defaults to '__Mustache_'.
60
+ * 'template_class_prefix' => '__MyTemplates_',
61
+ *
62
+ * // A Mustache cache instance or a cache directory string for compiled templates.
63
+ * // Mustache will not cache templates unless this is set.
64
+ * 'cache' => dirname(__FILE__).'/tmp/cache/mustache',
65
+ *
66
+ * // Override default permissions for cache files. Defaults to using the system-defined umask. It is
67
+ * // *strongly* recommended that you configure your umask properly rather than overriding permissions here.
68
+ * 'cache_file_mode' => 0666,
69
+ *
70
+ * // Optionally, enable caching for lambda section templates. This is generally not recommended, as lambda
71
+ * // sections are often too dynamic to benefit from caching.
72
+ * 'cache_lambda_templates' => true,
73
+ *
74
+ * // A Mustache template loader instance. Uses a StringLoader if not specified.
75
+ * 'loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views'),
76
+ *
77
+ * // A Mustache loader instance for partials.
78
+ * 'partials_loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views/partials'),
79
+ *
80
+ * // An array of Mustache partials. Useful for quick-and-dirty string template loading, but not as
81
+ * // efficient or lazy as a Filesystem (or database) loader.
82
+ * 'partials' => array('foo' => file_get_contents(dirname(__FILE__).'/views/partials/foo.mustache')),
83
+ *
84
+ * // An array of 'helpers'. Helpers can be global variables or objects, closures (e.g. for higher order
85
+ * // sections), or any other valid Mustache context value. They will be prepended to the context stack,
86
+ * // so they will be available in any template loaded by this Mustache instance.
87
+ * 'helpers' => array('i18n' => function ($text) {
88
+ * // do something translatey here...
89
+ * }),
90
+ *
91
+ * // An 'escape' callback, responsible for escaping double-mustache variables.
92
+ * 'escape' => function ($value) {
93
+ * return htmlspecialchars($buffer, ENT_COMPAT, 'UTF-8');
94
+ * },
95
+ *
96
+ * // Type argument for `htmlspecialchars`. Defaults to ENT_COMPAT. You may prefer ENT_QUOTES.
97
+ * 'entity_flags' => ENT_QUOTES,
98
+ *
99
+ * // Character set for `htmlspecialchars`. Defaults to 'UTF-8'. Use 'UTF-8'.
100
+ * 'charset' => 'ISO-8859-1',
101
+ *
102
+ * // A Mustache Logger instance. No logging will occur unless this is set. Using a PSR-3 compatible
103
+ * // logging library -- such as Monolog -- is highly recommended. A simple stream logger implementation is
104
+ * // available as well:
105
+ * 'logger' => new Mustache_Logger_StreamLogger('php://stderr'),
106
+ *
107
+ * // Only treat Closure instances and invokable classes as callable. If true, values like
108
+ * // `array('ClassName', 'methodName')` and `array($classInstance, 'methodName')`, which are traditionally
109
+ * // "callable" in PHP, are not called to resolve variables for interpolation or section contexts. This
110
+ * // helps protect against arbitrary code execution when user input is passed directly into the template.
111
+ * // This currently defaults to false, but will default to true in v3.0.
112
+ * 'strict_callables' => true,
113
+ * );
114
+ *
115
+ * @throws Mustache_Exception_InvalidArgumentException If `escape` option is not callable.
116
+ *
117
+ * @param array $options (default: array())
118
+ */
119
+ public function __construct(array $options = array())
120
+ {
121
+ if (isset($options['template_class_prefix'])) {
122
+ $this->templateClassPrefix = $options['template_class_prefix'];
123
+ }
124
+
125
+ if (isset($options['cache'])) {
126
+ $cache = $options['cache'];
127
+
128
+ if (is_string($cache)) {
129
+ $mode = isset($options['cache_file_mode']) ? $options['cache_file_mode'] : null;
130
+ $cache = new Mustache_Cache_FilesystemCache($cache, $mode);
131
+ }
132
+
133
+ $this->setCache($cache);
134
+ }
135
+
136
+ if (isset($options['cache_lambda_templates'])) {
137
+ $this->cacheLambdaTemplates = (bool) $options['cache_lambda_templates'];
138
+ }
139
+
140
+ if (isset($options['loader'])) {
141
+ $this->setLoader($options['loader']);
142
+ }
143
+
144
+ if (isset($options['partials_loader'])) {
145
+ $this->setPartialsLoader($options['partials_loader']);
146
+ }
147
+
148
+ if (isset($options['partials'])) {
149
+ $this->setPartials($options['partials']);
150
+ }
151
+
152
+ if (isset($options['helpers'])) {
153
+ $this->setHelpers($options['helpers']);
154
+ }
155
+
156
+ if (isset($options['escape'])) {
157
+ if (!is_callable($options['escape'])) {
158
+ throw new Mustache_Exception_InvalidArgumentException('Mustache Constructor "escape" option must be callable');
159
+ }
160
+
161
+ $this->escape = $options['escape'];
162
+ }
163
+
164
+ if (isset($options['entity_flags'])) {
165
+ $this->entityFlags = $options['entity_flags'];
166
+ }
167
+
168
+ if (isset($options['charset'])) {
169
+ $this->charset = $options['charset'];
170
+ }
171
+
172
+ if (isset($options['logger'])) {
173
+ $this->setLogger($options['logger']);
174
+ }
175
+
176
+ if (isset($options['strict_callables'])) {
177
+ $this->strictCallables = $options['strict_callables'];
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Shortcut 'render' invocation.
183
+ *
184
+ * Equivalent to calling `$mustache->loadTemplate($template)->render($context);`
185
+ *
186
+ * @see Mustache_Engine::loadTemplate
187
+ * @see Mustache_Template::render
188
+ *
189
+ * @param string $template
190
+ * @param mixed $context (default: array())
191
+ *
192
+ * @return string Rendered template
193
+ */
194
+ public function render($template, $context = array())
195
+ {
196
+ return $this->loadTemplate($template)->render($context);
197
+ }
198
+
199
+ /**
200
+ * Get the current Mustache escape callback.
201
+ *
202
+ * @return callable|null
203
+ */
204
+ public function getEscape()
205
+ {
206
+ return $this->escape;
207
+ }
208
+
209
+ /**
210
+ * Get the current Mustache entitity type to escape.
211
+ *
212
+ * @return int
213
+ */
214
+ public function getEntityFlags()
215
+ {
216
+ return $this->entityFlags;
217
+ }
218
+
219
+ /**
220
+ * Get the current Mustache character set.
221
+ *
222
+ * @return string
223
+ */
224
+ public function getCharset()
225
+ {
226
+ return $this->charset;
227
+ }
228
+
229
+ /**
230
+ * Set the Mustache template Loader instance.
231
+ *
232
+ * @param Mustache_Loader $loader
233
+ */
234
+ public function setLoader(Mustache_Loader $loader)
235
+ {
236
+ $this->loader = $loader;
237
+ }
238
+
239
+ /**
240
+ * Get the current Mustache template Loader instance.
241
+ *
242
+ * If no Loader instance has been explicitly specified, this method will instantiate and return
243
+ * a StringLoader instance.
244
+ *
245
+ * @return Mustache_Loader
246
+ */
247
+ public function getLoader()
248
+ {
249
+ if (!isset($this->loader)) {
250
+ $this->loader = new Mustache_Loader_StringLoader;
251
+ }
252
+
253
+ return $this->loader;
254
+ }
255
+
256
+ /**
257
+ * Set the Mustache partials Loader instance.
258
+ *
259
+ * @param Mustache_Loader $partialsLoader
260
+ */
261
+ public function setPartialsLoader(Mustache_Loader $partialsLoader)
262
+ {
263
+ $this->partialsLoader = $partialsLoader;
264
+ }
265
+
266
+ /**
267
+ * Get the current Mustache partials Loader instance.
268
+ *
269
+ * If no Loader instance has been explicitly specified, this method will instantiate and return
270
+ * an ArrayLoader instance.
271
+ *
272
+ * @return Mustache_Loader
273
+ */
274
+ public function getPartialsLoader()
275
+ {
276
+ if (!isset($this->partialsLoader)) {
277
+ $this->partialsLoader = new Mustache_Loader_ArrayLoader;
278
+ }
279
+
280
+ return $this->partialsLoader;
281
+ }
282
+
283
+ /**
284
+ * Set partials for the current partials Loader instance.
285
+ *
286
+ * @throws Mustache_Exception_RuntimeException If the current Loader instance is immutable
287
+ *
288
+ * @param array $partials (default: array())
289
+ */
290
+ public function setPartials(array $partials = array())
291
+ {
292
+ if (!isset($this->partialsLoader)) {
293
+ $this->partialsLoader = new Mustache_Loader_ArrayLoader;
294
+ }
295
+
296
+ if (!$this->partialsLoader instanceof Mustache_Loader_MutableLoader) {
297
+ throw new Mustache_Exception_RuntimeException('Unable to set partials on an immutable Mustache Loader instance');
298
+ }
299
+
300
+ $this->partialsLoader->setTemplates($partials);
301
+ }
302
+
303
+ /**
304
+ * Set an array of Mustache helpers.
305
+ *
306
+ * An array of 'helpers'. Helpers can be global variables or objects, closures (e.g. for higher order sections), or
307
+ * any other valid Mustache context value. They will be prepended to the context stack, so they will be available in
308
+ * any template loaded by this Mustache instance.
309
+ *
310
+ * @throws Mustache_Exception_InvalidArgumentException if $helpers is not an array or Traversable
311
+ *
312
+ * @param array|Traversable $helpers
313
+ */
314
+ public function setHelpers($helpers)
315
+ {
316
+ if (!is_array($helpers) && !$helpers instanceof Traversable) {
317
+ throw new Mustache_Exception_InvalidArgumentException('setHelpers expects an array of helpers');
318
+ }
319
+
320
+ $this->getHelpers()->clear();
321
+
322
+ foreach ($helpers as $name => $helper) {
323
+ $this->addHelper($name, $helper);
324
+ }
325
+ }
326
+
327
+ /**
328
+ * Get the current set of Mustache helpers.
329
+ *
330
+ * @see Mustache_Engine::setHelpers
331
+ *
332
+ * @return Mustache_HelperCollection
333
+ */
334
+ public function getHelpers()
335
+ {
336
+ if (!isset($this->helpers)) {
337
+ $this->helpers = new Mustache_HelperCollection;
338
+ }
339
+
340
+ return $this->helpers;
341
+ }
342
+
343
+ /**
344
+ * Add a new Mustache helper.
345
+ *
346
+ * @see Mustache_Engine::setHelpers
347
+ *
348
+ * @param string $name
349
+ * @param mixed $helper
350
+ */
351
+ public function addHelper($name, $helper)
352
+ {
353
+ $this->getHelpers()->add($name, $helper);
354
+ }
355
+
356
+ /**
357
+ * Get a Mustache helper by name.
358
+ *
359
+ * @see Mustache_Engine::setHelpers
360
+ *
361
+ * @param string $name
362
+ *
363
+ * @return mixed Helper
364
+ */
365
+ public function getHelper($name)
366
+ {
367
+ return $this->getHelpers()->get($name);
368
+ }
369
+
370
+ /**
371
+ * Check whether this Mustache instance has a helper.
372
+ *
373
+ * @see Mustache_Engine::setHelpers
374
+ *
375
+ * @param string $name
376
+ *
377
+ * @return boolean True if the helper is present
378
+ */
379
+ public function hasHelper($name)
380
+ {
381
+ return $this->getHelpers()->has($name);
382
+ }
383
+
384
+ /**
385
+ * Remove a helper by name.
386
+ *
387
+ * @see Mustache_Engine::setHelpers
388
+ *
389
+ * @param string $name
390
+ */
391
+ public function removeHelper($name)
392
+ {
393
+ $this->getHelpers()->remove($name);
394
+ }
395
+
396
+ /**
397
+ * Set the Mustache Logger instance.
398
+ *
399
+ * @throws Mustache_Exception_InvalidArgumentException If logger is not an instance of Mustache_Logger or Psr\Log\LoggerInterface.
400
+ *
401
+ * @param Mustache_Logger|Psr\Log\LoggerInterface $logger
402
+ */
403
+ public function setLogger($logger = null)
404
+ {
405
+ if ($logger !== null && !($logger instanceof Mustache_Logger || is_a($logger, 'Psr\\Log\\LoggerInterface'))) {
406
+ throw new Mustache_Exception_InvalidArgumentException('Expected an instance of Mustache_Logger or Psr\\Log\\LoggerInterface.');
407
+ }
408
+
409
+ if ($this->getCache()->getLogger() === null) {
410
+ $this->getCache()->setLogger($logger);
411
+ }
412
+
413
+ $this->logger = $logger;
414
+ }
415
+
416
+ /**
417
+ * Get the current Mustache Logger instance.
418
+ *
419
+ * @return Mustache_Logger|Psr\Log\LoggerInterface
420
+ */
421
+ public function getLogger()
422
+ {
423
+ return $this->logger;
424
+ }
425
+
426
+ /**
427
+ * Set the Mustache Tokenizer instance.
428
+ *
429
+ * @param Mustache_Tokenizer $tokenizer
430
+ */
431
+ public function setTokenizer(Mustache_Tokenizer $tokenizer)
432
+ {
433
+ $this->tokenizer = $tokenizer;
434
+ }
435
+
436
+ /**
437
+ * Get the current Mustache Tokenizer instance.
438
+ *
439
+ * If no Tokenizer instance has been explicitly specified, this method will instantiate and return a new one.
440
+ *
441
+ * @return Mustache_Tokenizer
442
+ */
443
+ public function getTokenizer()
444
+ {
445
+ if (!isset($this->tokenizer)) {
446
+ $this->tokenizer = new Mustache_Tokenizer;
447
+ }
448
+
449
+ return $this->tokenizer;
450
+ }
451
+
452
+ /**
453
+ * Set the Mustache Parser instance.
454
+ *
455
+ * @param Mustache_Parser $parser
456
+ */
457
+ public function setParser(Mustache_Parser $parser)
458
+ {
459
+ $this->parser = $parser;
460
+ }
461
+
462
+ /**
463
+ * Get the current Mustache Parser instance.
464
+ *
465
+ * If no Parser instance has been explicitly specified, this method will instantiate and return a new one.
466
+ *
467
+ * @return Mustache_Parser
468
+ */
469
+ public function getParser()
470
+ {
471
+ if (!isset($this->parser)) {
472
+ $this->parser = new Mustache_Parser;
473
+ }
474
+
475
+ return $this->parser;
476
+ }
477
+
478
+ /**
479
+ * Set the Mustache Compiler instance.
480
+ *
481
+ * @param Mustache_Compiler $compiler
482
+ */
483
+ public function setCompiler(Mustache_Compiler $compiler)
484
+ {
485
+ $this->compiler = $compiler;
486
+ }
487
+
488
+ /**
489
+ * Get the current Mustache Compiler instance.
490
+ *
491
+ * If no Compiler instance has been explicitly specified, this method will instantiate and return a new one.
492
+ *
493
+ * @return Mustache_Compiler
494
+ */
495
+ public function getCompiler()
496
+ {
497
+ if (!isset($this->compiler)) {
498
+ $this->compiler = new Mustache_Compiler;
499
+ }
500
+
501
+ return $this->compiler;
502
+ }
503
+
504
+ /**
505
+ * Set the Mustache Cache instance.
506
+ *
507
+ * @param Mustache_Cache $cache
508
+ */
509
+ public function setCache(Mustache_Cache $cache)
510
+ {
511
+ if (isset($this->logger) && $cache->getLogger() === null) {
512
+ $cache->setLogger($this->getLogger());
513
+ }
514
+
515
+ $this->cache = $cache;
516
+ }
517
+
518
+ /**
519
+ * Get the current Mustache Cache instance.
520
+ *
521
+ * If no Cache instance has been explicitly specified, this method will instantiate and return a new one.
522
+ *
523
+ * @return Mustache_Cache
524
+ */
525
+ public function getCache()
526
+ {
527
+ if (!isset($this->cache)) {
528
+ $this->setCache(new Mustache_Cache_NoopCache());
529
+ }
530
+
531
+ return $this->cache;
532
+ }
533
+
534
+ /**
535
+ * Get the current Lambda Cache instance.
536
+ *
537
+ * If 'cache_lambda_templates' is enabled, this is the default cache instance. Otherwise, it is a NoopCache.
538
+ *
539
+ * @see Mustache_Engine::getCache
540
+ *
541
+ * @return Mustache_Cache
542
+ */
543
+ protected function getLambdaCache()
544
+ {
545
+ if ($this->cacheLambdaTemplates) {
546
+ return $this->getCache();
547
+ }
548
+
549
+ if (!isset($this->lambdaCache)) {
550
+ $this->lambdaCache = new Mustache_Cache_NoopCache();
551
+ }
552
+
553
+ return $this->lambdaCache;
554
+ }
555
+
556
+ /**
557
+ * Helper method to generate a Mustache template class.
558
+ *
559
+ * @param string $source
560
+ *
561
+ * @return string Mustache Template class name
562
+ */
563
+ public function getTemplateClassName($source)
564
+ {
565
+ return $this->templateClassPrefix . md5(sprintf(
566
+ 'version:%s,escape:%s,entity_flags:%i,charset:%s,strict_callables:%s,source:%s',
567
+ self::VERSION,
568
+ isset($this->escape) ? 'custom' : 'default',
569
+ $this->entityFlags,
570
+ $this->charset,
571
+ $this->strictCallables ? 'true' : 'false',
572
+ $source
573
+ ));
574
+ }
575
+
576
+ /**
577
+ * Load a Mustache Template by name.
578
+ *
579
+ * @param string $name
580
+ *
581
+ * @return Mustache_Template
582
+ */
583
+ public function loadTemplate($name)
584
+ {
585
+ return $this->loadSource($this->getLoader()->load($name));
586
+ }
587
+
588
+ /**
589
+ * Load a Mustache partial Template by name.
590
+ *
591
+ * This is a helper method used internally by Template instances for loading partial templates. You can most likely
592
+ * ignore it completely.
593
+ *
594
+ * @param string $name
595
+ *
596
+ * @return Mustache_Template
597
+ */
598
+ public function loadPartial($name)
599
+ {
600
+ try {
601
+ if (isset($this->partialsLoader)) {
602
+ $loader = $this->partialsLoader;
603
+ } elseif (isset($this->loader) && !$this->loader instanceof Mustache_Loader_StringLoader) {
604
+ $loader = $this->loader;
605
+ } else {
606
+ throw new Mustache_Exception_UnknownTemplateException($name);
607
+ }
608
+
609
+ return $this->loadSource($loader->load($name));
610
+ } catch (Mustache_Exception_UnknownTemplateException $e) {
611
+ // If the named partial cannot be found, log then return null.
612
+ $this->log(
613
+ Mustache_Logger::WARNING,
614
+ 'Partial not found: "{name}"',
615
+ array('name' => $e->getTemplateName())
616
+ );
617
+ }
618
+ }
619
+
620
+ /**
621
+ * Load a Mustache lambda Template by source.
622
+ *
623
+ * This is a helper method used by Template instances to generate subtemplates for Lambda sections. You can most
624
+ * likely ignore it completely.
625
+ *
626
+ * @param string $source
627
+ * @param string $delims (default: null)
628
+ *
629
+ * @return Mustache_Template
630
+ */
631
+ public function loadLambda($source, $delims = null)
632
+ {
633
+ if ($delims !== null) {
634
+ $source = $delims . "\n" . $source;
635
+ }
636
+
637
+ return $this->loadSource($source, $this->getLambdaCache());
638
+ }
639
+
640
+ /**
641
+ * Instantiate and return a Mustache Template instance by source.
642
+ *
643
+ * Optionally provide a Mustache_Cache instance. This is used internally by Mustache_Engine::loadLambda to respect
644
+ * the 'cache_lambda_templates' configuration option.
645
+ *
646
+ * @see Mustache_Engine::loadTemplate
647
+ * @see Mustache_Engine::loadPartial
648
+ * @see Mustache_Engine::loadLambda
649
+ *
650
+ * @param string $source
651
+ * @param Mustache_Cache $cache (default: null)
652
+ *
653
+ * @return Mustache_Template
654
+ */
655
+ private function loadSource($source, Mustache_Cache $cache = null)
656
+ {
657
+ $className = $this->getTemplateClassName($source);
658
+
659
+ if (!isset($this->templates[$className])) {
660
+ if ($cache === null) {
661
+ $cache = $this->getCache();
662
+ }
663
+
664
+ if (!class_exists($className, false)) {
665
+ if (!$cache->load($className)) {
666
+ $compiled = $this->compile($source);
667
+ $cache->cache($className, $compiled);
668
+ }
669
+ }
670
+
671
+ $this->log(
672
+ Mustache_Logger::DEBUG,
673
+ 'Instantiating template: "{className}"',
674
+ array('className' => $className)
675
+ );
676
+
677
+ $this->templates[$className] = new $className($this);
678
+ }
679
+
680
+ return $this->templates[$className];
681
+ }
682
+
683
+ /**
684
+ * Helper method to tokenize a Mustache template.
685
+ *
686
+ * @see Mustache_Tokenizer::scan
687
+ *
688
+ * @param string $source
689
+ *
690
+ * @return array Tokens
691
+ */
692
+ private function tokenize($source)
693
+ {
694
+ return $this->getTokenizer()->scan($source);
695
+ }
696
+
697
+ /**
698
+ * Helper method to parse a Mustache template.
699
+ *
700
+ * @see Mustache_Parser::parse
701
+ *
702
+ * @param string $source
703
+ *
704
+ * @return array Token tree
705
+ */
706
+ private function parse($source)
707
+ {
708
+ return $this->getParser()->parse($this->tokenize($source));
709
+ }
710
+
711
+ /**
712
+ * Helper method to compile a Mustache template.
713
+ *
714
+ * @see Mustache_Compiler::compile
715
+ *
716
+ * @param string $source
717
+ *
718
+ * @return string generated Mustache template class code
719
+ */
720
+ private function compile($source)
721
+ {
722
+ $tree = $this->parse($source);
723
+ $name = $this->getTemplateClassName($source);
724
+
725
+ $this->log(
726
+ Mustache_Logger::INFO,
727
+ 'Compiling template to "{className}" class',
728
+ array('className' => $name)
729
+ );
730
+
731
+ return $this->getCompiler()->compile($source, $tree, $name, isset($this->escape), $this->charset, $this->strictCallables, $this->entityFlags);
732
+ }
733
+
734
+ /**
735
+ * Add a log record if logging is enabled.
736
+ *
737
+ * @param integer $level The logging level
738
+ * @param string $message The log message
739
+ * @param array $context The log context
740
+ */
741
+ private function log($level, $message, array $context = array())
742
+ {
743
+ if (isset($this->logger)) {
744
+ $this->logger->log($level, $message, $context);
745
+ }
746
+ }
747
+ }
vendor/mustache/mustache/src/Mustache/Exception.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * A Mustache Exception interface.
14
+ */
15
+ interface Mustache_Exception
16
+ {
17
+ // This space intentionally left blank.
18
+ }
vendor/mustache/mustache/src/Mustache/Exception/InvalidArgumentException.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Invalid argument exception.
14
+ */
15
+ class Mustache_Exception_InvalidArgumentException extends InvalidArgumentException implements Mustache_Exception
16
+ {
17
+ // This space intentionally left blank.
18
+ }
vendor/mustache/mustache/src/Mustache/Exception/LogicException.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Logic exception.
14
+ */
15
+ class Mustache_Exception_LogicException extends LogicException implements Mustache_Exception
16
+ {
17
+ // This space intentionally left blank.
18
+ }
vendor/mustache/mustache/src/Mustache/Exception/RuntimeException.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Runtime exception.
14
+ */
15
+ class Mustache_Exception_RuntimeException extends RuntimeException implements Mustache_Exception
16
+ {
17
+ // This space intentionally left blank.
18
+ }
vendor/mustache/mustache/src/Mustache/Exception/SyntaxException.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Mustache syntax exception.
14
+ */
15
+ class Mustache_Exception_SyntaxException extends LogicException implements Mustache_Exception
16
+ {
17
+ protected $token;
18
+
19
+ /**
20
+ * @param string $msg
21
+ * @param array $token
22
+ */
23
+ public function __construct($msg, array $token)
24
+ {
25
+ $this->token = $token;
26
+ parent::__construct($msg);
27
+ }
28
+
29
+ /**
30
+ * @return array
31
+ */
32
+ public function getToken()
33
+ {
34
+ return $this->token;
35
+ }
36
+ }
vendor/mustache/mustache/src/Mustache/Exception/UnknownFilterException.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Unknown filter exception.
14
+ */
15
+ class Mustache_Exception_UnknownFilterException extends UnexpectedValueException implements Mustache_Exception
16
+ {
17
+ protected $filterName;
18
+
19
+ /**
20
+ * @param string $filterName
21
+ */
22
+ public function __construct($filterName)
23
+ {
24
+ $this->filterName = $filterName;
25
+ parent::__construct(sprintf('Unknown filter: %s', $filterName));
26
+ }
27
+
28
+ public function getFilterName()
29
+ {
30
+ return $this->filterName;
31
+ }
32
+ }
vendor/mustache/mustache/src/Mustache/Exception/UnknownHelperException.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Unknown helper exception.
14
+ */
15
+ class Mustache_Exception_UnknownHelperException extends InvalidArgumentException implements Mustache_Exception
16
+ {
17
+ protected $helperName;
18
+
19
+ /**
20
+ * @param string $helperName
21
+ */
22
+ public function __construct($helperName)
23
+ {
24
+ $this->helperName = $helperName;
25
+ parent::__construct(sprintf('Unknown helper: %s', $helperName));
26
+ }
27
+
28
+ public function getHelperName()
29
+ {
30
+ return $this->helperName;
31
+ }
32
+ }
vendor/mustache/mustache/src/Mustache/Exception/UnknownTemplateException.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Unknown template exception.
14
+ */
15
+ class Mustache_Exception_UnknownTemplateException extends InvalidArgumentException implements Mustache_Exception
16
+ {
17
+ protected $templateName;
18
+
19
+ /**
20
+ * @param string $templateName
21
+ */
22
+ public function __construct($templateName)
23
+ {
24
+ $this->templateName = $templateName;
25
+ parent::__construct(sprintf('Unknown template: %s', $templateName));
26
+ }
27
+
28
+ public function getTemplateName()
29
+ {
30
+ return $this->templateName;
31
+ }
32
+ }
vendor/mustache/mustache/src/Mustache/HelperCollection.php ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * A collection of helpers for a Mustache instance.
14
+ */
15
+ class Mustache_HelperCollection
16
+ {
17
+ private $helpers = array();
18
+
19
+ /**
20
+ * Helper Collection constructor.
21
+ *
22
+ * Optionally accepts an array (or Traversable) of `$name => $helper` pairs.
23
+ *
24
+ * @throws Mustache_Exception_InvalidArgumentException if the $helpers argument isn't an array or Traversable
25
+ *
26
+ * @param array|Traversable $helpers (default: null)
27
+ */
28
+ public function __construct($helpers = null)
29
+ {
30
+ if ($helpers === null) {
31
+ return;
32
+ }
33
+
34
+ if (!is_array($helpers) && !$helpers instanceof Traversable) {
35
+ throw new Mustache_Exception_InvalidArgumentException('HelperCollection constructor expects an array of helpers');
36
+ }
37
+
38
+ foreach ($helpers as $name => $helper) {
39
+ $this->add($name, $helper);
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Magic mutator.
45
+ *
46
+ * @see Mustache_HelperCollection::add
47
+ *
48
+ * @param string $name
49
+ * @param mixed $helper
50
+ */
51
+ public function __set($name, $helper)
52
+ {
53
+ $this->add($name, $helper);
54
+ }
55
+
56
+ /**
57
+ * Add a helper to this collection.
58
+ *
59
+ * @param string $name
60
+ * @param mixed $helper
61
+ */
62
+ public function add($name, $helper)
63
+ {
64
+ $this->helpers[$name] = $helper;
65
+ }
66
+
67
+ /**
68
+ * Magic accessor.
69
+ *
70
+ * @see Mustache_HelperCollection::get
71
+ *
72
+ * @param string $name
73
+ *
74
+ * @return mixed Helper
75
+ */
76
+ public function __get($name)
77
+ {
78
+ return $this->get($name);
79
+ }
80
+
81
+ /**
82
+ * Get a helper by name.
83
+ *
84
+ * @throws Mustache_Exception_UnknownHelperException If helper does not exist.
85
+ *
86
+ * @param string $name
87
+ *
88
+ * @return mixed Helper
89
+ */
90
+ public function get($name)
91
+ {
92
+ if (!$this->has($name)) {
93
+ throw new Mustache_Exception_UnknownHelperException($name);
94
+ }
95
+
96
+ return $this->helpers[$name];
97
+ }
98
+
99
+ /**
100
+ * Magic isset().
101
+ *
102
+ * @see Mustache_HelperCollection::has
103
+ *
104
+ * @param string $name
105
+ *
106
+ * @return boolean True if helper is present
107
+ */
108
+ public function __isset($name)
109
+ {
110
+ return $this->has($name);
111
+ }
112
+
113
+ /**
114
+ * Check whether a given helper is present in the collection.
115
+ *
116
+ * @param string $name
117
+ *
118
+ * @return boolean True if helper is present
119
+ */
120
+ public function has($name)
121
+ {
122
+ return array_key_exists($name, $this->helpers);
123
+ }
124
+
125
+ /**
126
+ * Magic unset().
127
+ *
128
+ * @see Mustache_HelperCollection::remove
129
+ *
130
+ * @param string $name
131
+ */
132
+ public function __unset($name)
133
+ {
134
+ $this->remove($name);
135
+ }
136
+
137
+ /**
138
+ * Check whether a given helper is present in the collection.
139
+ *
140
+ * @throws Mustache_Exception_UnknownHelperException if the requested helper is not present.
141
+ *
142
+ * @param string $name
143
+ */
144
+ public function remove($name)
145
+ {
146
+ if (!$this->has($name)) {
147
+ throw new Mustache_Exception_UnknownHelperException($name);
148
+ }
149
+
150
+ unset($this->helpers[$name]);
151
+ }
152
+
153
+ /**
154
+ * Clear the helper collection.
155
+ *
156
+ * Removes all helpers from this collection
157
+ */
158
+ public function clear()
159
+ {
160
+ $this->helpers = array();
161
+ }
162
+
163
+ /**
164
+ * Check whether the helper collection is empty.
165
+ *
166
+ * @return boolean True if the collection is empty
167
+ */
168
+ public function isEmpty()
169
+ {
170
+ return empty($this->helpers);
171
+ }
172
+ }
vendor/mustache/mustache/src/Mustache/LambdaHelper.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Mustache Lambda Helper.
14
+ *
15
+ * Passed as the second argument to section lambdas (higher order sections),
16
+ * giving them access to a `render` method for rendering a string with the
17
+ * current context.
18
+ */
19
+ class Mustache_LambdaHelper
20
+ {
21
+ private $mustache;
22
+ private $context;
23
+
24
+ /**
25
+ * Mustache Lambda Helper constructor.
26
+ *
27
+ * @param Mustache_Engine $mustache Mustache engine instance.
28
+ * @param Mustache_Context $context Rendering context.
29
+ */
30
+ public function __construct(Mustache_Engine $mustache, Mustache_Context $context)
31
+ {
32
+ $this->mustache = $mustache;
33
+ $this->context = $context;
34
+ }
35
+
36
+ /**
37
+ * Render a string as a Mustache template with the current rendering context.
38
+ *
39
+ * @param string $string
40
+ *
41
+ * @return string Rendered template.
42
+ */
43
+ public function render($string)
44
+ {
45
+ return $this->mustache
46
+ ->loadLambda((string) $string)
47
+ ->renderInternal($this->context);
48
+ }
49
+ }
vendor/mustache/mustache/src/Mustache/Loader.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Mustache Template Loader interface.
14
+ */
15
+ interface Mustache_Loader
16
+ {
17
+ /**
18
+ * Load a Template by name.
19
+ *
20
+ * @throws Mustache_Exception_UnknownTemplateException If a template file is not found.
21
+ *
22
+ * @param string $name
23
+ *
24
+ * @return string Mustache Template source
25
+ */
26
+ public function load($name);
27
+ }
vendor/mustache/mustache/src/Mustache/Loader/ArrayLoader.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Mustache Template array Loader implementation.
14
+ *
15
+ * An ArrayLoader instance loads Mustache Template source by name from an initial array:
16
+ *
17
+ * $loader = new ArrayLoader(
18
+ * 'foo' => '{{ bar }}',
19
+ * 'baz' => 'Hey {{ qux }}!'
20
+ * );
21
+ *
22
+ * $tpl = $loader->load('foo'); // '{{ bar }}'
23
+ *
24
+ * The ArrayLoader is used internally as a partials loader by Mustache_Engine instance when an array of partials
25
+ * is set. It can also be used as a quick-and-dirty Template loader.
26
+ */
27
+ class Mustache_Loader_ArrayLoader implements Mustache_Loader, Mustache_Loader_MutableLoader
28
+ {
29
+ private $templates;
30
+
31
+ /**
32
+ * ArrayLoader constructor.
33
+ *
34
+ * @param array $templates Associative array of Template source (default: array())
35
+ */
36
+ public function __construct(array $templates = array())
37
+ {
38
+ $this->templates = $templates;
39
+ }
40
+
41
+ /**
42
+ * Load a Template.
43
+ *
44
+ * @throws Mustache_Exception_UnknownTemplateException If a template file is not found.
45
+ *
46
+ * @param string $name
47
+ *
48
+ * @return string Mustache Template source
49
+ */
50
+ public function load($name)
51
+ {
52
+ if (!isset($this->templates[$name])) {
53
+ throw new Mustache_Exception_UnknownTemplateException($name);
54
+ }
55
+
56
+ return $this->templates[$name];
57
+ }
58
+
59
+ /**
60
+ * Set an associative array of Template sources for this loader.
61
+ *
62
+ * @param array $templates
63
+ */
64
+ public function setTemplates(array $templates)
65
+ {
66
+ $this->templates = $templates;
67
+ }
68
+
69
+ /**
70
+ * Set a Template source by name.
71
+ *
72
+ * @param string $name
73
+ * @param string $template Mustache Template source
74
+ */
75
+ public function setTemplate($name, $template)
76
+ {
77
+ $this->templates[$name] = $template;
78
+ }
79
+ }
vendor/mustache/mustache/src/Mustache/Loader/CascadingLoader.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * A Mustache Template cascading loader implementation, which delegates to other
14
+ * Loader instances.
15
+ */
16
+ class Mustache_Loader_CascadingLoader implements Mustache_Loader
17
+ {
18
+ private $loaders;
19
+
20
+ /**
21
+ * Construct a CascadingLoader with an array of loaders:
22
+ *
23
+ * $loader = new Mustache_Loader_CascadingLoader(array(
24
+ * new Mustache_Loader_InlineLoader(__FILE__, __COMPILER_HALT_OFFSET__),
25
+ * new Mustache_Loader_FilesystemLoader(__DIR__.'/templates')
26
+ * ));
27
+ *
28
+ * @param Mustache_Loader[] $loaders
29
+ */
30
+ public function __construct(array $loaders = array())
31
+ {
32
+ $this->loaders = array();
33
+ foreach ($loaders as $loader) {
34
+ $this->addLoader($loader);
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Add a Loader instance.
40
+ *
41
+ * @param Mustache_Loader $loader
42
+ */
43
+ public function addLoader(Mustache_Loader $loader)
44
+ {
45
+ $this->loaders[] = $loader;
46
+ }
47
+
48
+ /**
49
+ * Load a Template by name.
50
+ *
51
+ * @throws Mustache_Exception_UnknownTemplateException If a template file is not found.
52
+ *
53
+ * @param string $name
54
+ *
55
+ * @return string Mustache Template source
56
+ */
57
+ public function load($name)
58
+ {
59
+ foreach ($this->loaders as $loader) {
60
+ try {
61
+ return $loader->load($name);
62
+ } catch (Mustache_Exception_UnknownTemplateException $e) {
63
+ // do nothing, check the next loader.
64
+ }
65
+ }
66
+
67
+ throw new Mustache_Exception_UnknownTemplateException($name);
68
+ }
69
+ }
vendor/mustache/mustache/src/Mustache/Loader/FilesystemLoader.php ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Mustache Template filesystem Loader implementation.
14
+ *
15
+ * A FilesystemLoader instance loads Mustache Template source from the filesystem by name:
16
+ *
17
+ * $loader = new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views');
18
+ * $tpl = $loader->load('foo'); // equivalent to `file_get_contents(dirname(__FILE__).'/views/foo.mustache');
19
+ *
20
+ * This is probably the most useful Mustache Loader implementation. It can be used for partials and normal Templates:
21
+ *
22
+ * $m = new Mustache(array(
23
+ * 'loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views'),
24
+ * 'partials_loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views/partials'),
25
+ * ));
26
+ */
27
+ class Mustache_Loader_FilesystemLoader implements Mustache_Loader
28
+ {
29
+ private $baseDir;
30
+ private $extension = '.mustache';
31
+ private $templates = array();
32
+
33
+ /**
34
+ * Mustache filesystem Loader constructor.
35
+ *
36
+ * Passing an $options array allows overriding certain Loader options during instantiation:
37
+ *
38
+ * $options = array(
39
+ * // The filename extension used for Mustache templates. Defaults to '.mustache'
40
+ * 'extension' => '.ms',
41
+ * );
42
+ *
43
+ * @throws Mustache_Exception_RuntimeException if $baseDir does not exist.
44
+ *
45
+ * @param string $baseDir Base directory containing Mustache template files.
46
+ * @param array $options Array of Loader options (default: array())
47
+ */
48
+ public function __construct($baseDir, array $options = array())
49
+ {
50
+ $this->baseDir = $baseDir;
51
+
52
+ if (strpos($this->baseDir, '://') === -1) {
53
+ $this->baseDir = realpath($this->baseDir);
54
+ }
55
+
56
+ if (!is_dir($this->baseDir)) {
57
+ throw new Mustache_Exception_RuntimeException(sprintf('FilesystemLoader baseDir must be a directory: %s', $baseDir));
58
+ }
59
+
60
+ if (array_key_exists('extension', $options)) {
61
+ if (empty($options['extension'])) {
62
+ $this->extension = '';
63
+ } else {
64
+ $this->extension = '.' . ltrim($options['extension'], '.');
65
+ }
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Load a Template by name.
71
+ *
72
+ * $loader = new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views');
73
+ * $loader->load('admin/dashboard'); // loads "./views/admin/dashboard.mustache";
74
+ *
75
+ * @param string $name
76
+ *
77
+ * @return string Mustache Template source
78
+ */
79
+ public function load($name)
80
+ {
81
+ if (!isset($this->templates[$name])) {
82
+ $this->templates[$name] = $this->loadFile($name);
83
+ }
84
+
85
+ return $this->templates[$name];
86
+ }
87
+
88
+ /**
89
+ * Helper function for loading a Mustache file by name.
90
+ *
91
+ * @throws Mustache_Exception_UnknownTemplateException If a template file is not found.
92
+ *
93
+ * @param string $name
94
+ *
95
+ * @return string Mustache Template source
96
+ */
97
+ protected function loadFile($name)
98
+ {
99
+ $fileName = $this->getFileName($name);
100
+
101
+ if (!file_exists($fileName)) {
102
+ throw new Mustache_Exception_UnknownTemplateException($name);
103
+ }
104
+
105
+ return file_get_contents($fileName);
106
+ }
107
+
108
+ /**
109
+ * Helper function for getting a Mustache template file name.
110
+ *
111
+ * @param string $name
112
+ *
113
+ * @return string Template file name
114
+ */
115
+ protected function getFileName($name)
116
+ {
117
+ $fileName = $this->baseDir . '/' . $name;
118
+ if (substr($fileName, 0 - strlen($this->extension)) !== $this->extension) {
119
+ $fileName .= $this->extension;
120
+ }
121
+
122
+ return $fileName;
123
+ }
124
+ }
vendor/mustache/mustache/src/Mustache/Loader/InlineLoader.php ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * A Mustache Template loader for inline templates.
14
+ *
15
+ * With the InlineLoader, templates can be defined at the end of any PHP source
16
+ * file:
17
+ *
18
+ * $loader = new Mustache_Loader_InlineLoader(__FILE__, __COMPILER_HALT_OFFSET__);
19
+ * $hello = $loader->load('hello');
20
+ * $goodbye = $loader->load('goodbye');
21
+ *
22
+ * __halt_compiler();
23
+ *
24
+ * @@ hello
25
+ * Hello, {{ planet }}!
26
+ *
27
+ * @@ goodbye
28
+ * Goodbye, cruel {{ planet }}
29
+ *
30
+ * Templates are deliniated by lines containing only `@@ name`.
31
+ *
32
+ * The InlineLoader is well-suited to micro-frameworks such as Silex:
33
+ *
34
+ * $app->register(new MustacheServiceProvider, array(
35
+ * 'mustache.loader' => new Mustache_Loader_InlineLoader(__FILE__, __COMPILER_HALT_OFFSET__)
36
+ * ));
37
+ *
38
+ * $app->get('/{name}', function ($name) use ($app) {
39
+ * return $app['mustache']->render('hello', compact('name'));
40
+ * })
41
+ * ->value('name', 'world');
42
+ *
43
+ * // ...
44
+ *
45
+ * __halt_compiler();
46
+ *
47
+ * @@ hello
48
+ * Hello, {{ name }}!
49
+ *
50
+ */
51
+ class Mustache_Loader_InlineLoader implements Mustache_Loader
52
+ {
53
+ protected $fileName;
54
+ protected $offset;
55
+ protected $templates;
56
+
57
+ /**
58
+ * The InlineLoader requires a filename and offset to process templates.
59
+ * The magic constants `__FILE__` and `__COMPILER_HALT_OFFSET__` are usually
60
+ * perfectly suited to the job:
61
+ *
62
+ * $loader = new Mustache_Loader_InlineLoader(__FILE__, __COMPILER_HALT_OFFSET__);
63
+ *
64
+ * Note that this only works if the loader is instantiated inside the same
65
+ * file as the inline templates. If the templates are located in another
66
+ * file, it would be necessary to manually specify the filename and offset.
67
+ *
68
+ * @param string $fileName The file to parse for inline templates
69
+ * @param int $offset A string offset for the start of the templates.
70
+ * This usually coincides with the `__halt_compiler`
71
+ * call, and the `__COMPILER_HALT_OFFSET__`.
72
+ */
73
+ public function __construct($fileName, $offset)
74
+ {
75
+ if (!is_file($fileName)) {
76
+ throw new Mustache_Exception_InvalidArgumentException('InlineLoader expects a valid filename.');
77
+ }
78
+
79
+ if (!is_int($offset) || $offset < 0) {
80
+ throw new Mustache_Exception_InvalidArgumentException('InlineLoader expects a valid file offset.');
81
+ }
82
+
83
+ $this->fileName = $fileName;
84
+ $this->offset = $offset;
85
+ }
86
+
87
+ /**
88
+ * Load a Template by name.
89
+ *
90
+ * @throws Mustache_Exception_UnknownTemplateException If a template file is not found.
91
+ *
92
+ * @param string $name
93
+ *
94
+ * @return string Mustache Template source
95
+ */
96
+ public function load($name)
97
+ {
98
+ $this->loadTemplates();
99
+
100
+ if (!array_key_exists($name, $this->templates)) {
101
+ throw new Mustache_Exception_UnknownTemplateException($name);
102
+ }
103
+
104
+ return $this->templates[$name];
105
+ }
106
+
107
+ /**
108
+ * Parse and load templates from the end of a source file.
109
+ */
110
+ protected function loadTemplates()
111
+ {
112
+ if ($this->templates === null) {
113
+ $this->templates = array();
114
+ $data = file_get_contents($this->fileName, false, null, $this->offset);
115
+ foreach (preg_split("/^@@(?= [\w\d\.]+$)/m", $data, -1) as $chunk) {
116
+ if (trim($chunk)) {
117
+ list($name, $content) = explode("\n", $chunk, 2);
118
+ $this->templates[trim($name)] = trim($content);
119
+ }
120
+ }
121
+ }
122
+ }
123
+ }
vendor/mustache/mustache/src/Mustache/Loader/MutableLoader.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Mustache Template mutable Loader interface.
14
+ */
15
+ interface Mustache_Loader_MutableLoader
16
+ {
17
+ /**
18
+ * Set an associative array of Template sources for this loader.
19
+ *
20
+ * @param array $templates
21
+ *
22
+ * @return void
23
+ */
24
+ public function setTemplates(array $templates);
25
+
26
+ /**
27
+ * Set a Template source by name.
28
+ *
29
+ * @param string $name
30
+ * @param string $template Mustache Template source
31
+ *
32
+ * @return void
33
+ */
34
+ public function setTemplate($name, $template);
35
+ }
vendor/mustache/mustache/src/Mustache/Loader/StringLoader.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Mustache Template string Loader implementation.
14
+ *
15
+ * A StringLoader instance is essentially a noop. It simply passes the 'name' argument straight through:
16
+ *
17
+ * $loader = new StringLoader;
18
+ * $tpl = $loader->load('{{ foo }}'); // '{{ foo }}'
19
+ *
20
+ * This is the default Template Loader instance used by Mustache:
21
+ *
22
+ * $m = new Mustache;
23
+ * $tpl = $m->loadTemplate('{{ foo }}');
24
+ * echo $tpl->render(array('foo' => 'bar')); // "bar"
25
+ */
26
+ class Mustache_Loader_StringLoader implements Mustache_Loader
27
+ {
28
+ /**
29
+ * Load a Template by source.
30
+ *
31
+ * @param string $name Mustache Template source
32
+ *
33
+ * @return string Mustache Template source
34
+ */
35
+ public function load($name)
36
+ {
37
+ return $name;
38
+ }
39
+ }
vendor/mustache/mustache/src/Mustache/Logger.php ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Describes a Mustache logger instance
14
+ *
15
+ * This is identical to the Psr\Log\LoggerInterface.
16
+ *
17
+ * The message MUST be a string or object implementing __toString().
18
+ *
19
+ * The message MAY contain placeholders in the form: {foo} where foo
20
+ * will be replaced by the context data in key "foo".
21
+ *
22
+ * The context array can contain arbitrary data, the only assumption that
23
+ * can be made by implementors is that if an Exception instance is given
24
+ * to produce a stack trace, it MUST be in a key named "exception".
25
+ *
26
+ * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
27
+ * for the full interface specification.
28
+ */
29
+ interface Mustache_Logger
30
+ {
31
+ /**
32
+ * Psr\Log compatible log levels
33
+ */
34
+ const EMERGENCY = 'emergency';
35
+ const ALERT = 'alert';
36
+ const CRITICAL = 'critical';
37
+ const ERROR = 'error';
38
+ const WARNING = 'warning';
39
+ const NOTICE = 'notice';
40
+ const INFO = 'info';
41
+ const DEBUG = 'debug';
42
+
43
+ /**
44
+ * System is unusable.
45
+ *
46
+ * @param string $message
47
+ * @param array $context
48
+ *
49
+ * @return null
50
+ */
51
+ public function emergency($message, array $context = array());
52
+
53
+ /**
54
+ * Action must be taken immediately.
55
+ *
56
+ * Example: Entire website down, database unavailable, etc. This should
57
+ * trigger the SMS alerts and wake you up.
58
+ *
59
+ * @param string $message
60
+ * @param array $context
61
+ *
62
+ * @return null
63
+ */
64
+ public function alert($message, array $context = array());
65
+
66
+ /**
67
+ * Critical conditions.
68
+ *
69
+ * Example: Application component unavailable, unexpected exception.
70
+ *
71
+ * @param string $message
72
+ * @param array $context
73
+ *
74
+ * @return null
75
+ */
76
+ public function critical($message, array $context = array());
77
+
78
+ /**
79
+ * Runtime errors that do not require immediate action but should typically
80
+ * be logged and monitored.
81
+ *
82
+ * @param string $message
83
+ * @param array $context
84
+ *
85
+ * @return null
86
+ */
87
+ public function error($message, array $context = array());
88
+
89
+ /**
90
+ * Exceptional occurrences that are not errors.
91
+ *
92
+ * Example: Use of deprecated APIs, poor use of an API, undesirable things
93
+ * that are not necessarily wrong.
94
+ *
95
+ * @param string $message
96
+ * @param array $context
97
+ *
98
+ * @return null
99
+ */
100
+ public function warning($message, array $context = array());
101
+
102
+ /**
103
+ * Normal but significant events.
104
+ *
105
+ * @param string $message
106
+ * @param array $context
107
+ *
108
+ * @return null
109
+ */
110
+ public function notice($message, array $context = array());
111
+
112
+ /**
113
+ * Interesting events.
114
+ *
115
+ * Example: User logs in, SQL logs.
116
+ *
117
+ * @param string $message
118
+ * @param array $context
119
+ *
120
+ * @return null
121
+ */
122
+ public function info($message, array $context = array());
123
+
124
+ /**
125
+ * Detailed debug information.
126
+ *
127
+ * @param string $message
128
+ * @param array $context
129
+ *
130
+ * @return null
131
+ */
132
+ public function debug($message, array $context = array());
133
+
134
+ /**
135
+ * Logs with an arbitrary level.
136
+ *
137
+ * @param mixed $level
138
+ * @param string $message
139
+ * @param array $context
140
+ *
141
+ * @return null
142
+ */
143
+ public function log($level, $message, array $context = array());
144
+ }
vendor/mustache/mustache/src/Mustache/Logger/AbstractLogger.php ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * This is a simple Logger implementation that other Loggers can inherit from.
14
+ *
15
+ * This is identical to the Psr\Log\AbstractLogger.
16
+ *
17
+ * It simply delegates all log-level-specific methods to the `log` method to
18
+ * reduce boilerplate code that a simple Logger that does the same thing with
19
+ * messages regardless of the error level has to implement.
20
+ */
21
+ abstract class Mustache_Logger_AbstractLogger implements Mustache_Logger
22
+ {
23
+ /**
24
+ * System is unusable.
25
+ *
26
+ * @param string $message
27
+ * @param array $context
28
+ */
29
+ public function emergency($message, array $context = array())
30
+ {
31
+ $this->log(Mustache_Logger::EMERGENCY, $message, $context);
32
+ }
33
+
34
+ /**
35
+ * Action must be taken immediately.
36
+ *
37
+ * Example: Entire website down, database unavailable, etc. This should
38
+ * trigger the SMS alerts and wake you up.
39
+ *
40
+ * @param string $message
41
+ * @param array $context
42
+ */
43
+ public function alert($message, array $context = array())
44
+ {
45
+ $this->log(Mustache_Logger::ALERT, $message, $context);
46
+ }
47
+
48
+ /**
49
+ * Critical conditions.
50
+ *
51
+ * Example: Application component unavailable, unexpected exception.
52
+ *
53
+ * @param string $message
54
+ * @param array $context
55
+ */
56
+ public function critical($message, array $context = array())
57
+ {
58
+ $this->log(Mustache_Logger::CRITICAL, $message, $context);
59
+ }
60
+
61
+ /**
62
+ * Runtime errors that do not require immediate action but should typically
63
+ * be logged and monitored.
64
+ *
65
+ * @param string $message
66
+ * @param array $context
67
+ */
68
+ public function error($message, array $context = array())
69
+ {
70
+ $this->log(Mustache_Logger::ERROR, $message, $context);
71
+ }
72
+
73
+ /**
74
+ * Exceptional occurrences that are not errors.
75
+ *
76
+ * Example: Use of deprecated APIs, poor use of an API, undesirable things
77
+ * that are not necessarily wrong.
78
+ *
79
+ * @param string $message
80
+ * @param array $context
81
+ */
82
+ public function warning($message, array $context = array())
83
+ {
84
+ $this->log(Mustache_Logger::WARNING, $message, $context);
85
+ }
86
+
87
+ /**
88
+ * Normal but significant events.
89
+ *
90
+ * @param string $message
91
+ * @param array $context
92
+ */
93
+ public function notice($message, array $context = array())
94
+ {
95
+ $this->log(Mustache_Logger::NOTICE, $message, $context);
96
+ }
97
+
98
+ /**
99
+ * Interesting events.
100
+ *
101
+ * Example: User logs in, SQL logs.
102
+ *
103
+ * @param string $message
104
+ * @param array $context
105
+ */
106
+ public function info($message, array $context = array())
107
+ {
108
+ $this->log(Mustache_Logger::INFO, $message, $context);
109
+ }
110
+
111
+ /**
112
+ * Detailed debug information.
113
+ *
114
+ * @param string $message
115
+ * @param array $context
116
+ */
117
+ public function debug($message, array $context = array())
118
+ {
119
+ $this->log(Mustache_Logger::DEBUG, $message, $context);
120
+ }
121
+ }
vendor/mustache/mustache/src/Mustache/Logger/StreamLogger.php ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * A Mustache Stream Logger.
14
+ *
15
+ * The Stream Logger wraps a file resource instance (such as a stream) or a
16
+ * stream URL. All log messages over the threshold level will be appended to
17
+ * this stream.
18
+ *
19
+ * Hint: Try `php://stderr` for your stream URL.
20
+ */
21
+ class Mustache_Logger_StreamLogger extends Mustache_Logger_AbstractLogger
22
+ {
23
+ protected static $levels = array(
24
+ self::DEBUG => 100,
25
+ self::INFO => 200,
26
+ self::NOTICE => 250,
27
+ self::WARNING => 300,
28
+ self::ERROR => 400,
29
+ self::CRITICAL => 500,
30
+ self::ALERT => 550,
31
+ self::EMERGENCY => 600,
32
+ );
33
+
34
+ protected $level;
35
+ protected $stream = null;
36
+ protected $url = null;
37
+
38
+ /**
39
+ * @throws InvalidArgumentException if the logging level is unknown.
40
+ *
41
+ * @param resource|string $stream Resource instance or URL
42
+ * @param integer $level The minimum logging level at which this handler will be triggered
43
+ */
44
+ public function __construct($stream, $level = Mustache_Logger::ERROR)
45
+ {
46
+ $this->setLevel($level);
47
+
48
+ if (is_resource($stream)) {
49
+ $this->stream = $stream;
50
+ } else {
51
+ $this->url = $stream;
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Close stream resources.
57
+ */
58
+ public function __destruct()
59
+ {
60
+ if (is_resource($this->stream)) {
61
+ fclose($this->stream);
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Set the minimum logging level.
67
+ *
68
+ * @throws Mustache_Exception_InvalidArgumentException if the logging level is unknown.
69
+ *
70
+ * @param integer $level The minimum logging level which will be written
71
+ */
72
+ public function setLevel($level)
73
+ {
74
+ if (!array_key_exists($level, self::$levels)) {
75
+ throw new Mustache_Exception_InvalidArgumentException(sprintf('Unexpected logging level: %s', $level));
76
+ }
77
+
78
+ $this->level = $level;
79
+ }
80
+
81
+ /**
82
+ * Get the current minimum logging level.
83
+ *
84
+ * @return integer
85
+ */
86
+ public function getLevel()
87
+ {
88
+ return $this->level;
89
+ }
90
+
91
+ /**
92
+ * Logs with an arbitrary level.
93
+ *
94
+ * @throws Mustache_Exception_InvalidArgumentException if the logging level is unknown.
95
+ *
96
+ * @param mixed $level
97
+ * @param string $message
98
+ * @param array $context
99
+ */
100
+ public function log($level, $message, array $context = array())
101
+ {
102
+ if (!array_key_exists($level, self::$levels)) {
103
+ throw new Mustache_Exception_InvalidArgumentException(sprintf('Unexpected logging level: %s', $level));
104
+ }
105
+
106
+ if (self::$levels[$level] >= self::$levels[$this->level]) {
107
+ $this->writeLog($level, $message, $context);
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Write a record to the log.
113
+ *
114
+ * @throws Mustache_Exception_LogicException If neither a stream resource nor url is present.
115
+ * @throws Mustache_Exception_RuntimeException If the stream url cannot be opened.
116
+ *
117
+ * @param integer $level The logging level
118
+ * @param string $message The log message
119
+ * @param array $context The log context
120
+ */
121
+ protected function writeLog($level, $message, array $context = array())
122
+ {
123
+ if (!is_resource($this->stream)) {
124
+ if (!isset($this->url)) {
125
+ throw new Mustache_Exception_LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
126
+ }
127
+
128
+ $this->stream = fopen($this->url, 'a');
129
+ if (!is_resource($this->stream)) {
130
+ // @codeCoverageIgnoreStart
131
+ throw new Mustache_Exception_RuntimeException(sprintf('The stream or file "%s" could not be opened.', $this->url));
132
+ // @codeCoverageIgnoreEnd
133
+ }
134
+ }
135
+
136
+ fwrite($this->stream, self::formatLine($level, $message, $context));
137
+ }
138
+
139
+ /**
140
+ * Gets the name of the logging level.
141
+ *
142
+ * @throws InvalidArgumentException if the logging level is unknown.
143
+ *
144
+ * @param integer $level
145
+ *
146
+ * @return string
147
+ */
148
+ protected static function getLevelName($level)
149
+ {
150
+ return strtoupper($level);
151
+ }
152
+
153
+ /**
154
+ * Format a log line for output.
155
+ *
156
+ * @param integer $level The logging level
157
+ * @param string $message The log message
158
+ * @param array $context The log context
159
+ *
160
+ * @return string
161
+ */
162
+ protected static function formatLine($level, $message, array $context = array())
163
+ {
164
+ return sprintf(
165
+ "%s: %s\n",
166
+ self::getLevelName($level),
167
+ self::interpolateMessage($message, $context)
168
+ );
169
+ }
170
+
171
+ /**
172
+ * Interpolate context values into the message placeholders.
173
+ *
174
+ * @param string $message
175
+ * @param array $context
176
+ *
177
+ * @return string
178
+ */
179
+ protected static function interpolateMessage($message, array $context = array())
180
+ {
181
+ if (strpos($message, '{') === false) {
182
+ return $message;
183
+ }
184
+
185
+ // build a replacement array with braces around the context keys
186
+ $replace = array();
187
+ foreach ($context as $key => $val) {
188
+ $replace['{' . $key . '}'] = $val;
189
+ }
190
+
191
+ // interpolate replacement values into the the message and return
192
+ return strtr($message, $replace);
193
+ }
194
+ }
vendor/mustache/mustache/src/Mustache/Parser.php ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Mustache Parser class.
14
+ *
15
+ * This class is responsible for turning a set of Mustache tokens into a parse tree.
16
+ */
17
+ class Mustache_Parser
18
+ {
19
+ private $lineNum;
20
+ private $lineTokens;
21
+
22
+ /**
23
+ * Process an array of Mustache tokens and convert them into a parse tree.
24
+ *
25
+ * @param array $tokens Set of Mustache tokens
26
+ *
27
+ * @return array Mustache token parse tree
28
+ */
29
+ public function parse(array $tokens = array())
30
+ {
31
+ $this->lineNum = -1;
32
+ $this->lineTokens = 0;
33
+
34
+ return $this->buildTree($tokens);
35
+ }
36
+
37
+ /**
38
+ * Helper method for recursively building a parse tree.
39
+ *
40
+ * @throws Mustache_Exception_SyntaxException when nesting errors or mismatched section tags are encountered.
41
+ *
42
+ * @param array &$tokens Set of Mustache tokens
43
+ * @param array $parent Parent token (default: null)
44
+ *
45
+ * @return array Mustache Token parse tree
46
+ */
47
+ private function buildTree(array &$tokens, array $parent = null)
48
+ {
49
+ $nodes = array();
50
+
51
+ while (!empty($tokens)) {
52
+ $token = array_shift($tokens);
53
+
54
+ if ($token[Mustache_Tokenizer::LINE] === $this->lineNum) {
55
+ $this->lineTokens++;
56
+ } else {
57
+ $this->lineNum = $token[Mustache_Tokenizer::LINE];
58
+ $this->lineTokens = 0;
59
+ }
60
+
61
+ switch ($token[Mustache_Tokenizer::TYPE]) {
62
+ case Mustache_Tokenizer::T_DELIM_CHANGE:
63
+ $this->clearStandaloneLines($nodes, $tokens);
64
+ break;
65
+
66
+ case Mustache_Tokenizer::T_SECTION:
67
+ case Mustache_Tokenizer::T_INVERTED:
68
+ $this->clearStandaloneLines($nodes, $tokens);
69
+ $nodes[] = $this->buildTree($tokens, $token);
70
+ break;
71
+
72
+ case Mustache_Tokenizer::T_END_SECTION:
73
+ if (!isset($parent)) {
74
+ $msg = sprintf(
75
+ 'Unexpected closing tag: /%s on line %d',
76
+ $token[Mustache_Tokenizer::NAME],
77
+ $token[Mustache_Tokenizer::LINE]
78
+ );
79
+ throw new Mustache_Exception_SyntaxException($msg, $token);
80
+ }
81
+
82
+ if ($token[Mustache_Tokenizer::NAME] !== $parent[Mustache_Tokenizer::NAME]) {
83
+ $msg = sprintf(
84
+ 'Nesting error: %s (on line %d) vs. %s (on line %d)',
85
+ $parent[Mustache_Tokenizer::NAME],
86
+ $parent[Mustache_Tokenizer::LINE],
87
+ $token[Mustache_Tokenizer::NAME],
88
+ $token[Mustache_Tokenizer::LINE]
89
+ );
90
+ throw new Mustache_Exception_SyntaxException($msg, $token);
91
+ }
92
+
93
+ $this->clearStandaloneLines($nodes, $tokens);
94
+ $parent[Mustache_Tokenizer::END] = $token[Mustache_Tokenizer::INDEX];
95
+ $parent[Mustache_Tokenizer::NODES] = $nodes;
96
+
97
+ return $parent;
98
+
99
+ case Mustache_Tokenizer::T_PARTIAL:
100
+ case Mustache_Tokenizer::T_PARTIAL_2:
101
+ // store the whitespace prefix for laters!
102
+ if ($indent = $this->clearStandaloneLines($nodes, $tokens)) {
103
+ $token[Mustache_Tokenizer::INDENT] = $indent[Mustache_Tokenizer::VALUE];
104
+ }
105
+ $nodes[] = $token;
106
+ break;
107
+
108
+ case Mustache_Tokenizer::T_PRAGMA:
109
+ case Mustache_Tokenizer::T_COMMENT:
110
+ $this->clearStandaloneLines($nodes, $tokens);
111
+ $nodes[] = $token;
112
+ break;
113
+
114
+ default:
115
+ $nodes[] = $token;
116
+ break;
117
+ }
118
+ }
119
+
120
+ if (isset($parent)) {
121
+ $msg = sprintf(
122
+ 'Missing closing tag: %s opened on line %d',
123
+ $parent[Mustache_Tokenizer::NAME],
124
+ $parent[Mustache_Tokenizer::LINE]
125
+ );
126
+ throw new Mustache_Exception_SyntaxException($msg, $parent);
127
+ }
128
+
129
+ return $nodes;
130
+ }
131
+
132
+ /**
133
+ * Clear standalone line tokens.
134
+ *
135
+ * Returns a whitespace token for indenting partials, if applicable.
136
+ *
137
+ * @param array $nodes Parsed nodes.
138
+ * @param array $tokens Tokens to be parsed.
139
+ *
140
+ * @return array Resulting indent token, if any.
141
+ */
142
+ private function clearStandaloneLines(array &$nodes, array &$tokens)
143
+ {
144
+ if ($this->lineTokens > 1) {
145
+ // this is the third or later node on this line, so it can't be standalone
146
+ return;
147
+ }
148
+
149
+ $prev = null;
150
+ if ($this->lineTokens === 1) {
151
+ // this is the second node on this line, so it can't be standalone
152
+ // unless the previous node is whitespace.
153
+ if ($prev = end($nodes)) {
154
+ if (!$this->tokenIsWhitespace($prev)) {
155
+ return;
156
+ }
157
+ }
158
+ }
159
+
160
+ if ($next = reset($tokens)) {
161
+ // If we're on a new line, bail.
162
+ if ($next[Mustache_Tokenizer::LINE] !== $this->lineNum) {
163
+ return;
164
+ }
165
+
166
+ // If the next token isn't whitespace, bail.
167
+ if (!$this->tokenIsWhitespace($next)) {
168
+ return;
169
+ }
170
+
171
+ if (count($tokens) !== 1) {
172
+ // Unless it's the last token in the template, the next token
173
+ // must end in newline for this to be standalone.
174
+ if (substr($next[Mustache_Tokenizer::VALUE], -1) !== "\n") {
175
+ return;
176
+ }
177
+ }
178
+
179
+ // Discard the whitespace suffix
180
+ array_shift($tokens);
181
+ }
182
+
183
+ if ($prev) {
184
+ // Return the whitespace prefix, if any
185
+ return array_pop($nodes);
186
+ }
187
+ }
188
+
189
+ /**
190
+ * Check whether token is a whitespace token.
191
+ *
192
+ * True if token type is T_TEXT and value is all whitespace characters.
193
+ *
194
+ * @param array $token
195
+ *
196
+ * @return boolean True if token is a whitespace token
197
+ */
198
+ private function tokenIsWhitespace(array $token)
199
+ {
200
+ if ($token[Mustache_Tokenizer::TYPE] == Mustache_Tokenizer::T_TEXT) {
201
+ return preg_match('/^\s*$/', $token[Mustache_Tokenizer::VALUE]);
202
+ }
203
+
204
+ return false;
205
+ }
206
+ }
vendor/mustache/mustache/src/Mustache/Template.php ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Abstract Mustache Template class.
14
+ *
15
+ * @abstract
16
+ */
17
+ abstract class Mustache_Template
18
+ {
19
+ /**
20
+ * @var Mustache_Engine
21
+ */
22
+ protected $mustache;
23
+
24
+ /**
25
+ * @var boolean
26
+ */
27
+ protected $strictCallables = false;
28
+
29
+ /**
30
+ * Mustache Template constructor.
31
+ *
32
+ * @param Mustache_Engine $mustache
33
+ */
34
+ public function __construct(Mustache_Engine $mustache)
35
+ {
36
+ $this->mustache = $mustache;
37
+ }
38
+
39
+ /**
40
+ * Mustache Template instances can be treated as a function and rendered by simply calling them:
41
+ *
42
+ * $m = new Mustache_Engine;
43
+ * $tpl = $m->loadTemplate('Hello, {{ name }}!');
44
+ * echo $tpl(array('name' => 'World')); // "Hello, World!"
45
+ *
46
+ * @see Mustache_Template::render
47
+ *
48
+ * @param mixed $context Array or object rendering context (default: array())
49
+ *
50
+ * @return string Rendered template
51
+ */
52
+ public function __invoke($context = array())
53
+ {
54
+ return $this->render($context);
55
+ }
56
+
57
+ /**
58
+ * Render this template given the rendering context.
59
+ *
60
+ * @param mixed $context Array or object rendering context (default: array())
61
+ *
62
+ * @return string Rendered template
63
+ */
64
+ public function render($context = array())
65
+ {
66
+ return $this->renderInternal($this->prepareContextStack($context));
67
+ }
68
+
69
+ /**
70
+ * Internal rendering method implemented by Mustache Template concrete subclasses.
71
+ *
72
+ * This is where the magic happens :)
73
+ *
74
+ * NOTE: This method is not part of the Mustache.php public API.
75
+ *
76
+ * @param Mustache_Context $context
77
+ * @param string $indent (default: '')
78
+ *
79
+ * @return string Rendered template
80
+ */
81
+ abstract public function renderInternal(Mustache_Context $context, $indent = '');
82
+
83
+ /**
84
+ * Tests whether a value should be iterated over (e.g. in a section context).
85
+ *
86
+ * In most languages there are two distinct array types: list and hash (or whatever you want to call them). Lists
87
+ * should be iterated, hashes should be treated as objects. Mustache follows this paradigm for Ruby, Javascript,
88
+ * Java, Python, etc.
89
+ *
90
+ * PHP, however, treats lists and hashes as one primitive type: array. So Mustache.php needs a way to distinguish
91
+ * between between a list of things (numeric, normalized array) and a set of variables to be used as section context
92
+ * (associative array). In other words, this will be iterated over:
93
+ *
94
+ * $items = array(
95
+ * array('name' => 'foo'),
96
+ * array('name' => 'bar'),
97
+ * array('name' => 'baz'),
98
+ * );
99
+ *
100
+ * ... but this will be used as a section context block:
101
+ *
102
+ * $items = array(
103
+ * 1 => array('name' => 'foo'),
104
+ * 'banana' => array('name' => 'bar'),
105
+ * 42 => array('name' => 'baz'),
106
+ * );
107
+ *
108
+ * @param mixed $value
109
+ *
110
+ * @return boolean True if the value is 'iterable'
111
+ */
112
+ protected function isIterable($value)
113
+ {
114
+ if (is_object($value)) {
115
+ return $value instanceof Traversable;
116
+ } elseif (is_array($value)) {
117
+ $i = 0;
118
+ foreach ($value as $k => $v) {
119
+ if ($k !== $i++) {
120
+ return false;
121
+ }
122
+ }
123
+
124
+ return true;
125
+ } else {
126
+ return false;
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Helper method to prepare the Context stack.
132
+ *
133
+ * Adds the Mustache HelperCollection to the stack's top context frame if helpers are present.
134
+ *
135
+ * @param mixed $context Optional first context frame (default: null)
136
+ *
137
+ * @return Mustache_Context
138
+ */
139
+ protected function prepareContextStack($context = null)
140
+ {
141
+ $stack = new Mustache_Context;
142
+
143
+ $helpers = $this->mustache->getHelpers();
144
+ if (!$helpers->isEmpty()) {
145
+ $stack->push($helpers);
146
+ }
147
+
148
+ if (!empty($context)) {
149
+ $stack->push($context);
150
+ }
151
+
152
+ return $stack;
153
+ }
154
+
155
+ /**
156
+ * Resolve a context value.
157
+ *
158
+ * Invoke the value if it is callable, otherwise return the value.
159
+ *
160
+ * @param mixed $value
161
+ * @param Mustache_Context $context
162
+ * @param string $indent
163
+ *
164
+ * @return string
165
+ */
166
+ protected function resolveValue($value, Mustache_Context $context, $indent = '')
167
+ {
168
+ if (($this->strictCallables ? is_object($value) : !is_string($value)) && is_callable($value)) {
169
+ return $this->mustache
170
+ ->loadLambda((string) call_user_func($value))
171
+ ->renderInternal($context, $indent);
172
+ }
173
+
174
+ return $value;
175
+ }
176
+ }
vendor/mustache/mustache/src/Mustache/Tokenizer.php ADDED
@@ -0,0 +1,327 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Mustache.php.
5
+ *
6
+ * (c) 2010-2014 Justin Hileman
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Mustache Tokenizer class.
14
+ *
15
+ * This class is responsible for turning raw template source into a set of Mustache tokens.
16
+ */
17
+ class Mustache_Tokenizer
18
+ {
19
+ // Finite state machine states
20
+ const IN_TEXT = 0;
21
+ const IN_TAG_TYPE = 1;
22
+ const IN_TAG = 2;
23
+
24
+ // Token types
25
+ const T_SECTION = '#';
26
+ const T_INVERTED = '^';
27
+ const T_END_SECTION = '/';
28
+ const T_COMMENT = '!';
29
+ const T_PARTIAL = '>';
30
+ const T_PARTIAL_2 = '<';
31
+ const T_DELIM_CHANGE = '=';
32
+ const T_ESCAPED = '_v';
33
+ const T_UNESCAPED = '{';
34
+ const T_UNESCAPED_2 = '&';
35
+ const T_TEXT = '_t';
36
+ const T_PRAGMA = '%';
37
+
38
+ // Valid token types
39
+ private static $tagTypes = array(
40
+ self::T_SECTION => true,
41
+ self::T_INVERTED => true,
42
+ self::T_END_SECTION => true,
43
+ self::T_COMMENT => true,
44
+ self::T_PARTIAL => true,
45
+ self::T_PARTIAL_2 => true,
46
+ self::T_DELIM_CHANGE => true,
47
+ self::T_ESCAPED => true,
48
+ self::T_UNESCAPED => true,
49
+ self::T_UNESCAPED_2 => true,
50
+ self::T_PRAGMA => true,
51
+ );
52
+
53
+ // Interpolated tags
54
+ private static $interpolatedTags = array(
55
+ self::T_ESCAPED => true,
56
+ self::T_UNESCAPED => true,
57
+ self::T_UNESCAPED_2 => true,
58
+ );
59
+
60
+ // Token properties
61
+ const TYPE = 'type';
62
+ const NAME = 'name';
63
+ const OTAG = 'otag';
64
+ const CTAG = 'ctag';
65
+ const LINE = 'line';
66
+ const INDEX = 'index';
67
+ const END = 'end';
68
+ const INDENT = 'indent';
69
+ const NODES = 'nodes';
70
+ const VALUE = 'value';
71
+
72
+ private $state;
73
+ private $tagType;
74
+ private $tag;
75
+ private $buffer;
76
+ private $tokens;
77
+ private $seenTag;
78
+ private $line;
79
+ private $otag;
80
+ private $ctag;
81
+ private $otagLen;
82
+ private $ctagLen;
83
+
84
+ /**
85
+ * Scan and tokenize template source.
86
+ *
87
+ * @throws Mustache_Exception_SyntaxException when mismatched section tags are encountered.
88
+ *
89
+ * @param string $text Mustache template source to tokenize
90
+ * @param string $delimiters Optionally, pass initial opening and closing delimiters (default: null)
91
+ *
92
+ * @return array Set of Mustache tokens
93
+ */
94
+ public function scan($text, $delimiters = null)
95
+ {
96
+ // Setting mbstring.func_overload makes things *really* slow.
97
+ // Let's do everyone a favor and scan this string as ASCII instead.
98
+ $encoding = null;
99
+ if (function_exists('mb_internal_encoding') && ini_get('mbstring.func_overload') & 2) {
100
+ $encoding = mb_internal_encoding();
101
+ mb_internal_encoding('ASCII');
102
+ }
103
+
104
+ $this->reset();
105
+
106
+ if ($delimiters = trim($delimiters)) {
107
+ $this->setDelimiters($delimiters);
108
+ }
109
+
110
+ $len = strlen($text);
111
+ for ($i = 0; $i < $len; $i++) {
112
+ switch ($this->state) {
113
+ case self::IN_TEXT:
114
+ if ($this->tagChange($this->otag, $this->otagLen, $text, $i)) {
115
+ $i--;
116
+ $this->flushBuffer();
117
+ $this->state = self::IN_TAG_TYPE;
118
+ } else {
119
+ $char = $text[$i];
120
+ $this->buffer .= $char;
121
+ if ($char === "\n") {
122
+ $this->flushBuffer();
123
+ $this->line++;
124
+ }
125
+ }
126
+ break;
127
+
128
+ case self::IN_TAG_TYPE:
129
+ $i += $this->otagLen - 1;
130
+ $char = $text[$i + 1];
131
+ if (isset(self::$tagTypes[$char])) {
132
+ $tag = $char;
133
+ $this->tagType = $tag;
134
+ } else {
135
+ $tag = null;
136
+ $this->tagType = self::T_ESCAPED;
137
+ }
138
+
139
+ if ($this->tagType === self::T_DELIM_CHANGE) {
140
+ $i = $this->changeDelimiters($text, $i);
141
+ $this->state = self::IN_TEXT;
142
+ } elseif ($this->tagType === self::T_PRAGMA) {
143
+ $i = $this->addPragma($text, $i);
144
+ $this->state = self::IN_TEXT;
145
+ } else {
146
+ if ($tag !== null) {
147
+ $i++;
148
+ }
149
+ $this->state = self::IN_TAG;
150
+ }
151
+ $this->seenTag = $i;
152
+ break;
153
+
154
+ default:
155
+ if ($this->tagChange($this->ctag, $this->ctagLen, $text, $i)) {
156
+ $token = array(
157
+ self::TYPE => $this->tagType,
158
+ self::NAME => trim($this->buffer),
159
+ self::OTAG => $this->otag,
160
+ self::CTAG => $this->ctag,
161
+ self::LINE => $this->line,
162
+ self::INDEX => ($this->tagType === self::T_END_SECTION) ? $this->seenTag - $this->otagLen : $i + $this->ctagLen
163
+ );
164
+
165
+ if ($this->tagType === self::T_UNESCAPED) {
166
+ // Clean up `{{{ tripleStache }}}` style tokens.
167
+ if ($this->ctag === '}}') {
168
+ if (($i + 2 < $len) && $text[$i + 2] === '}') {
169
+ $i++;
170
+ } else {
171
+ $msg = sprintf(
172
+ 'Mismatched tag delimiters: %s on line %d',
173
+ $token[self::NAME],
174
+ $token[self::LINE]
175
+ );
176
+
177
+ throw new Mustache_Exception_SyntaxException($msg, $token);
178
+ }
179
+ } else {
180
+ $lastName = $token[self::NAME];
181
+ if (substr($lastName, -1) === '}') {
182
+ $token[self::NAME] = trim(substr($lastName, 0, -1));
183
+ } else {
184
+ $msg = sprintf(
185
+ 'Mismatched tag delimiters: %s on line %d',
186
+ $token[self::NAME],
187
+ $token[self::LINE]
188
+ );
189
+
190
+ throw new Mustache_Exception_SyntaxException($msg, $token);
191
+ }
192
+ }
193
+ }
194
+
195
+ $this->buffer = '';
196
+ $i += $this->ctagLen - 1;
197
+ $this->state = self::IN_TEXT;
198
+ $this->tokens[] = $token;
199
+ } else {
200
+ $this->buffer .= $text[$i];
201
+ }
202
+ break;
203
+ }
204
+ }
205
+
206
+ $this->flushBuffer();
207
+
208
+ // Restore the user's encoding...
209
+ if ($encoding) {
210
+ mb_internal_encoding($encoding);
211
+ }
212
+
213
+ return $this->tokens;
214
+ }
215
+
216
+ /**
217
+ * Helper function to reset tokenizer internal state.
218
+ */
219
+ private function reset()
220
+ {
221
+ $this->state = self::IN_TEXT;
222
+ $this->tagType = null;
223
+ $this->tag = null;
224
+ $this->buffer = '';
225
+ $this->tokens = array();
226
+ $this->seenTag = false;
227
+ $this->line = 0;
228
+ $this->otag = '{{';
229
+ $this->ctag = '}}';
230
+ $this->otagLen = 2;
231
+ $this->ctagLen = 2;
232
+ }
233
+
234
+ /**
235
+ * Flush the current buffer to a token.
236
+ */
237
+ private function flushBuffer()
238
+ {
239
+ if (strlen($this->buffer) > 0) {
240
+ $this->tokens[] = array(
241
+ self::TYPE => self::T_TEXT,
242
+ self::LINE => $this->line,
243
+ self::VALUE => $this->buffer
244
+ );
245
+ $this->buffer = '';
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Change the current Mustache delimiters. Set new `otag` and `ctag` values.
251
+ *
252
+ * @param string $text Mustache template source
253
+ * @param int $index Current tokenizer index
254
+ *
255
+ * @return int New index value
256
+ */
257
+ private function changeDelimiters($text, $index)
258
+ {
259
+ $startIndex = strpos($text, '=', $index) + 1;
260
+ $close = '='.$this->ctag;
261
+ $closeIndex = strpos($text, $close, $index);
262
+
263
+ $this->setDelimiters(trim(substr($text, $startIndex, $closeIndex - $startIndex)));
264
+
265
+ $this->tokens[] = array(
266
+ self::TYPE => self::T_DELIM_CHANGE,
267
+ self::LINE => $this->line,
268
+ );
269
+
270
+ return $closeIndex + strlen($close) - 1;
271
+ }
272
+
273
+ /**
274
+ * Set the current Mustache `otag` and `ctag` delimiters.
275
+ *
276
+ * @param string $delimiters
277
+ */
278
+ private function setDelimiters($delimiters)
279
+ {
280
+ list($otag, $ctag) = explode(' ', $delimiters);
281
+ $this->otag = $otag;
282
+ $this->ctag = $ctag;
283
+ $this->otagLen = strlen($otag);
284
+ $this->ctagLen = strlen($ctag);
285
+ }
286
+
287
+ /**
288
+ * Add pragma token.
289
+ *
290
+ * Pragmas are hoisted to the front of the template, so all pragma tokens
291
+ * will appear at the front of the token list.
292
+ *
293
+ * @param string $text
294
+ * @param int $index
295
+ *
296
+ * @return int New index value
297
+ */
298
+ private function addPragma($text, $index)
299
+ {
300
+ $end = strpos($text, $this->ctag, $index);
301
+ $pragma = trim(substr($text, $index + 2, $end - $index - 2));
302
+
303
+ // Pragmas are hoisted to the front of the template.
304
+ array_unshift($this->tokens, array(
305
+ self::TYPE => self::T_PRAGMA,
306
+ self::NAME => $pragma,
307
+ self::LINE => 0,
308
+ ));
309
+
310
+ return $end + $this->ctagLen - 1;
311
+ }
312
+
313
+ /**
314
+ * Test whether it's time to change tags.
315
+ *
316
+ * @param string $tag Current tag name
317
+ * @param int $tagLen Current tag name length
318
+ * @param string $text Mustache template source
319
+ * @param int $index Current tokenizer index
320
+ *
321
+ * @return boolean True if this is a closing section tag
322
+ */
323
+ private function tagChange($tag, $tagLen, $text, $index)
324
+ {
325
+ return substr($text, $index, $tagLen) === $tag;
326
+ }
327
+ }
{core → vendor/scribu/lib-posts-to-posts}/api.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/autoload.php RENAMED
@@ -33,3 +33,9 @@ class P2P_Autoload {
33
  }
34
  }
35
 
 
 
 
 
 
 
33
  }
34
  }
35
 
36
+
37
+ P2P_Autoload::register( 'P2P_', dirname( __FILE__ ) );
38
+
39
+ require_once dirname( __FILE__ ) . '/util.php';
40
+ require_once dirname( __FILE__ ) . '/api.php';
41
+
vendor/scribu/lib-posts-to-posts/composer.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "scribu/lib-posts-to-posts",
3
+ "description": "A library for many-to-many relationships in WordPress",
4
+ "homepage": "https://github.com/scribu/wp-lib-posts-to-posts",
5
+ "license": "GPL-2.0+",
6
+ "minimum-stability": "dev",
7
+ "require": {
8
+ "scribu/scb-framework": "dev-master"
9
+ },
10
+ "autoload": {
11
+ "files": ["autoload.php"]
12
+ }
13
+ }
{core → vendor/scribu/lib-posts-to-posts}/connection-type-factory.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/connection-type.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/determinate-connection-type.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/directed-connection-type.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/direction-strategy.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/exception.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/indeterminate-connection-type.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/indeterminate-directed-connection-type.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/item-any.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/item-attachment.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/item-post.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/item-user.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/item.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/list-renderer.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/list.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/query-post.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/query-user.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/query.php RENAMED
@@ -85,13 +85,13 @@ class P2P_Query {
85
  }
86
 
87
  if ( isset( $q['connected_direction'] ) )
88
- $directions = (array) _p2p_pluck( $q, 'connected_direction' );
89
  else
90
  $directions = array();
91
 
92
  $item = isset( $q['connected_items'] ) ? $q['connected_items'] : 'any';
93
 
94
- $ctypes = (array) _p2p_pluck( $q, 'connected_type' );
95
 
96
  $p2p_types = self::expand_ctypes( $item, $directions, $object_type, $ctypes );
97
 
85
  }
86
 
87
  if ( isset( $q['connected_direction'] ) )
88
+ $directions = (array) $q['connected_direction'];
89
  else
90
  $directions = array();
91
 
92
  $item = isset( $q['connected_items'] ) ? $q['connected_items'] : 'any';
93
 
94
+ $ctypes = (array) $q['connected_type'];
95
 
96
  $p2p_types = self::expand_ctypes( $item, $directions, $object_type, $ctypes );
97
 
{core → vendor/scribu/lib-posts-to-posts}/reciprocal-connection-type.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/shortcodes.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/side-attachment.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/side-post.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/side-user.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/side.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/storage.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/url-query.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/util.php RENAMED
File without changes
{core → vendor/scribu/lib-posts-to-posts}/widget.php RENAMED
File without changes
{scb → vendor/scribu/scb-framework}/AdminPage.php RENAMED
File without changes
{scb → vendor/scribu/scb-framework}/BoxesPage.php RENAMED
File without changes
{scb → vendor/scribu/scb-framework}/Cron.php RENAMED
File without changes
{scb → vendor/scribu/scb-framework}/Forms.php RENAMED
File without changes
{scb → vendor/scribu/scb-framework}/Hooks.php RENAMED
File without changes
{scb → vendor/scribu/scb-framework}/Options.php RENAMED
File without changes
{scb → vendor/scribu/scb-framework}/PostMetabox.php RENAMED
@@ -72,7 +72,7 @@ class scbPostMetabox {
72
  $error_fields = array();
73
 
74
  if ( isset( $form_data['_error_data_' . $this->id ] ) ) {
75
- $data = unserialize( $form_data['_error_data_' . $this->id ] );
76
 
77
  $error_fields = $data['fields'];
78
  $form_data = $data['data'];
@@ -167,14 +167,14 @@ class scbPostMetabox {
167
  return $post_data;
168
  }
169
 
170
- protected function validate_post_data( $post_data ) {
171
  return false;
172
  }
173
 
174
  private function get_meta( $post_id ) {
175
  $meta = get_post_custom( $post_id );
176
  foreach ( $meta as $key => $values )
177
- $meta[$key] = $meta[$key][0];
178
 
179
  return $meta;
180
  }
72
  $error_fields = array();
73
 
74
  if ( isset( $form_data['_error_data_' . $this->id ] ) ) {
75
+ $data = maybe_unserialize( $form_data['_error_data_' . $this->id ] );
76
 
77
  $error_fields = $data['fields'];
78
  $form_data = $data['data'];
167
  return $post_data;
168
  }
169
 
170
+ protected function validate_post_data( $post_data, $post_id ) {
171
  return false;
172
  }
173
 
174
  private function get_meta( $post_id ) {
175
  $meta = get_post_custom( $post_id );
176
  foreach ( $meta as $key => $values )
177
+ $meta[ $key ] = maybe_unserialize( $meta[ $key ][0] );
178
 
179
  return $meta;
180
  }
{scb → vendor/scribu/scb-framework}/Table.php RENAMED
File without changes
{scb → vendor/scribu/scb-framework}/Util.php RENAMED
@@ -28,7 +28,9 @@ class scbUtil {
28
  $content = str_replace( array( "'", "\n" ), array( '"', '' ), ob_get_clean() );
29
 
30
  echo "<script type='text/javascript'>\n";
 
31
  echo "jQuery(function ($) { $('head').prepend('$content'); });\n";
 
32
  echo "</script>";
33
  }
34
 
28
  $content = str_replace( array( "'", "\n" ), array( '"', '' ), ob_get_clean() );
29
 
30
  echo "<script type='text/javascript'>\n";
31
+ echo "//<![CDATA[";
32
  echo "jQuery(function ($) { $('head').prepend('$content'); });\n";
33
+ echo "//]]>";
34
  echo "</script>";
35
  }
36
 
{scb → vendor/scribu/scb-framework}/Widget.php RENAMED
File without changes
{scb → vendor/scribu/scb-framework}/composer.json RENAMED
File without changes
{scb → vendor/scribu/scb-framework}/load-composer.php RENAMED
File without changes
{scb → vendor/scribu/scb-framework}/load.php RENAMED
File without changes