MailPoet Newsletters (New) - Version 3.0.0-beta.32

Version Description

  • 2017-05-23 =
  • Added: API methods for 3rd party plugins to add subscribers to MailPoet. Which plugins should we connect to?
Download this release

Release Info

Developer wysija
Plugin Icon 128x128 MailPoet Newsletters (New)
Version 3.0.0-beta.32
Comparing to
See all releases

Code changes from version 3.0.0-beta.31 to 3.0.0-beta.32

Files changed (51) hide show
  1. assets/js/admin_vendor.js +42 -3
  2. assets/js/form_editor.js +361 -331
  3. assets/js/mailpoet.js +149 -133
  4. assets/js/mp2migrator.js +259 -0
  5. assets/js/public.js +149 -133
  6. lang/index.php +0 -3
  7. lang/mailpoet-de_DE.mo +0 -0
  8. lang/mailpoet-de_DE.po +3 -3
  9. lang/mailpoet-pt_PT.mo +0 -0
  10. lang/mailpoet-pt_PT.po +2 -2
  11. lang/mailpoet.pot +90 -79
  12. lib/API/API.php +7 -189
  13. lib/API/JSON/API.php +200 -0
  14. lib/API/{Access.php → JSON/Access.php} +1 -1
  15. lib/API/{Endpoint.php → JSON/Endpoint.php} +1 -1
  16. lib/API/{Error.php → JSON/Error.php} +1 -1
  17. lib/API/{ErrorResponse.php → JSON/ErrorResponse.php} +1 -1
  18. lib/API/{Response.php → JSON/Response.php} +1 -1
  19. lib/API/{SuccessResponse.php → JSON/SuccessResponse.php} +1 -1
  20. lib/API/{Endpoints → JSON}/index.php +0 -0
  21. lib/API/{Endpoints → JSON}/v1/AutomatedLatestContent.php +2 -2
  22. lib/API/{Endpoints → JSON}/v1/CustomFields.php +3 -3
  23. lib/API/{Endpoints → JSON}/v1/Forms.php +3 -3
  24. lib/API/{Endpoints → JSON}/v1/ImportExport.php +2 -2
  25. lib/API/{Endpoints → JSON}/v1/Mailer.php +3 -3
  26. lib/API/{Endpoints → JSON}/v1/NewsletterTemplates.php +3 -3
  27. lib/API/{Endpoints → JSON}/v1/Newsletters.php +3 -3
  28. lib/API/{Endpoints → JSON}/v1/Segments.php +3 -3
  29. lib/API/{Endpoints → JSON}/v1/SendingQueue.php +3 -3
  30. lib/API/{Endpoints → JSON}/v1/Services.php +3 -3
  31. lib/API/{Endpoints → JSON}/v1/Settings.php +3 -3
  32. lib/API/{Endpoints → JSON}/v1/Setup.php +2 -2
  33. lib/API/{Endpoints → JSON}/v1/Subscribers.php +4 -4
  34. lib/API/{Endpoints → JSON}/v1/index.php +0 -0
  35. lib/API/MP/index.php +0 -0
  36. lib/API/MP/v1/API.php +132 -0
  37. lib/API/MP/v1/index.php +0 -0
  38. lib/Config/Initializer.php +3 -4
  39. lib/Form/Widget.php +1 -1
  40. lib/Models/CustomField.php +7 -1
  41. lib/Models/Segment.php +7 -5
  42. lib/Models/Subscriber.php +27 -20
  43. lib/Subscription/Form.php +2 -2
  44. mailpoet.php +3 -3
  45. readme.txt +6 -3
  46. vendor/autoload.php +1 -1
  47. vendor/composer/ClassLoader.php +31 -5
  48. vendor/composer/autoload_classmap.php +21 -19
  49. vendor/composer/autoload_real.php +8 -8
  50. vendor/composer/autoload_static.php +26 -24
  51. vendor/composer/installed.json +12 -12
assets/js/admin_vendor.js CHANGED
@@ -22187,6 +22187,20 @@ webpackJsonp([1],[
22187
  return emptyFunction.thatReturnsNull;
22188
  }
22189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22190
  function validate(props, propName, componentName, location, propFullName) {
22191
  for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
22192
  var checker = arrayOfTypeCheckers[i];
@@ -22319,6 +22333,9 @@ webpackJsonp([1],[
22319
  // This handles more types than `getPropType`. Only used for error messages.
22320
  // See `createPrimitiveTypeChecker`.
22321
  function getPreciseType(propValue) {
 
 
 
22322
  var propType = getPropType(propValue);
22323
  if (propType === 'object') {
22324
  if (propValue instanceof Date) {
@@ -22330,6 +22347,23 @@ webpackJsonp([1],[
22330
  return propType;
22331
  }
22332
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22333
  // Returns class name of the object, if any.
22334
  function getClassName(propValue) {
22335
  if (!propValue.constructor || !propValue.constructor.name) {
@@ -22451,11 +22485,14 @@ webpackJsonp([1],[
22451
 
22452
  var emptyFunction = __webpack_require__(14);
22453
  var invariant = __webpack_require__(10);
 
22454
 
22455
  module.exports = function() {
22456
- // Important!
22457
- // Keep this list in sync with production version in `./factoryWithTypeCheckers.js`.
22458
- function shim() {
 
 
22459
  invariant(
22460
  false,
22461
  'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +
@@ -22467,6 +22504,8 @@ webpackJsonp([1],[
22467
  function getShim() {
22468
  return shim;
22469
  };
 
 
22470
  var ReactPropTypes = {
22471
  array: shim,
22472
  bool: shim,
22187
  return emptyFunction.thatReturnsNull;
22188
  }
22189
 
22190
+ for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
22191
+ var checker = arrayOfTypeCheckers[i];
22192
+ if (typeof checker !== 'function') {
22193
+ warning(
22194
+ false,
22195
+ 'Invalid argument supplid to oneOfType. Expected an array of check functions, but ' +
22196
+ 'received %s at index %s.',
22197
+ getPostfixForTypeWarning(checker),
22198
+ i
22199
+ );
22200
+ return emptyFunction.thatReturnsNull;
22201
+ }
22202
+ }
22203
+
22204
  function validate(props, propName, componentName, location, propFullName) {
22205
  for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
22206
  var checker = arrayOfTypeCheckers[i];
22333
  // This handles more types than `getPropType`. Only used for error messages.
22334
  // See `createPrimitiveTypeChecker`.
22335
  function getPreciseType(propValue) {
22336
+ if (typeof propValue === 'undefined' || propValue === null) {
22337
+ return '' + propValue;
22338
+ }
22339
  var propType = getPropType(propValue);
22340
  if (propType === 'object') {
22341
  if (propValue instanceof Date) {
22347
  return propType;
22348
  }
22349
 
22350
+ // Returns a string that is postfixed to a warning about an invalid type.
22351
+ // For example, "undefined" or "of type array"
22352
+ function getPostfixForTypeWarning(value) {
22353
+ var type = getPreciseType(value);
22354
+ switch (type) {
22355
+ case 'array':
22356
+ case 'object':
22357
+ return 'an ' + type;
22358
+ case 'boolean':
22359
+ case 'date':
22360
+ case 'regexp':
22361
+ return 'a ' + type;
22362
+ default:
22363
+ return type;
22364
+ }
22365
+ }
22366
+
22367
  // Returns class name of the object, if any.
22368
  function getClassName(propValue) {
22369
  if (!propValue.constructor || !propValue.constructor.name) {
22485
 
22486
  var emptyFunction = __webpack_require__(14);
22487
  var invariant = __webpack_require__(10);
22488
+ var ReactPropTypesSecret = __webpack_require__(187);
22489
 
22490
  module.exports = function() {
22491
+ function shim(props, propName, componentName, location, propFullName, secret) {
22492
+ if (secret === ReactPropTypesSecret) {
22493
+ // It is still safe when called from React.
22494
+ return;
22495
+ }
22496
  invariant(
22497
  false,
22498
  'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +
22504
  function getShim() {
22505
  return shim;
22506
  };
22507
+ // Important!
22508
+ // Keep this list in sync with production version in `./factoryWithTypeCheckers.js`.
22509
  var ReactPropTypes = {
22510
  array: shim,
22511
  bool: shim,
assets/js/form_editor.js CHANGED
@@ -2236,7 +2236,7 @@ webpackJsonp([2],{
2236
  ch = dir < 0 ? lineObj.text.length - 1 : 0;
2237
  var targetTop = measureCharPrepared(cm, prep, ch).top;
2238
  ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch);
2239
- if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1, true); }
2240
  } else { ch = dir < 0 ? part.to : part.from; }
2241
  return new Pos(lineNo, ch, sticky)
2242
  }
@@ -4250,49 +4250,6 @@ webpackJsonp([2],{
4250
  setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false; } }, 150);
4251
  }
4252
 
4253
- // Re-align line numbers and gutter marks to compensate for
4254
- // horizontal scrolling.
4255
- function alignHorizontally(cm) {
4256
- var display = cm.display, view = display.view;
4257
- if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return }
4258
- var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
4259
- var gutterW = display.gutters.offsetWidth, left = comp + "px";
4260
- for (var i = 0; i < view.length; i++) { if (!view[i].hidden) {
4261
- if (cm.options.fixedGutter) {
4262
- if (view[i].gutter)
4263
- { view[i].gutter.style.left = left; }
4264
- if (view[i].gutterBackground)
4265
- { view[i].gutterBackground.style.left = left; }
4266
- }
4267
- var align = view[i].alignable;
4268
- if (align) { for (var j = 0; j < align.length; j++)
4269
- { align[j].style.left = left; } }
4270
- } }
4271
- if (cm.options.fixedGutter)
4272
- { display.gutters.style.left = (comp + gutterW) + "px"; }
4273
- }
4274
-
4275
- // Used to ensure that the line number gutter is still the right
4276
- // size for the current document size. Returns true when an update
4277
- // is needed.
4278
- function maybeUpdateLineNumberWidth(cm) {
4279
- if (!cm.options.lineNumbers) { return false }
4280
- var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
4281
- if (last.length != display.lineNumChars) {
4282
- var test = display.measure.appendChild(elt("div", [elt("div", last)],
4283
- "CodeMirror-linenumber CodeMirror-gutter-elt"));
4284
- var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
4285
- display.lineGutter.style.width = "";
4286
- display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1;
4287
- display.lineNumWidth = display.lineNumInnerWidth + padding;
4288
- display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
4289
- display.lineGutter.style.width = display.lineNumWidth + "px";
4290
- updateGutterSpace(cm);
4291
- return true
4292
- }
4293
- return false
4294
- }
4295
-
4296
  // Read the actual heights of the rendered lines, and update their
4297
  // stored heights to match.
4298
  function updateHeightsInViewport(cm) {
@@ -4351,139 +4308,218 @@ webpackJsonp([2],{
4351
  return {from: from, to: Math.max(to, from + 1)}
4352
  }
4353
 
4354
- // Sync the scrollable area and scrollbars, ensure the viewport
4355
- // covers the visible area.
4356
- function setScrollTop(cm, val) {
4357
- if (Math.abs(cm.doc.scrollTop - val) < 2) { return }
4358
- cm.doc.scrollTop = val;
4359
- if (!gecko) { updateDisplaySimple(cm, {top: val}); }
4360
- if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val; }
4361
- cm.display.scrollbars.setScrollTop(val);
4362
- if (gecko) { updateDisplaySimple(cm); }
4363
- startWorker(cm, 100);
 
 
 
 
 
 
 
 
 
 
4364
  }
4365
- // Sync scroller and scrollbar, ensure the gutter elements are
4366
- // aligned.
4367
- function setScrollLeft(cm, val, isScroller) {
4368
- if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) { return }
4369
- val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
4370
- cm.doc.scrollLeft = val;
4371
- alignHorizontally(cm);
4372
- if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val; }
4373
- cm.display.scrollbars.setScrollLeft(val);
 
 
 
 
 
 
 
 
 
 
 
4374
  }
4375
 
4376
- // Since the delta values reported on mouse wheel events are
4377
- // unstandardized between browsers and even browser versions, and
4378
- // generally horribly unpredictable, this code starts by measuring
4379
- // the scroll effect that the first few mouse wheel events have,
4380
- // and, from that, detects the way it can convert deltas to pixel
4381
- // offsets afterwards.
4382
- //
4383
- // The reason we want to know the amount a wheel event will scroll
4384
- // is that it gives us a chance to update the display before the
4385
- // actual scrolling happens, reducing flickering.
4386
 
4387
- var wheelSamples = 0;
4388
- var wheelPixelsPerUnit = null;
4389
- // Fill in a browser-detected starting value on browsers where we
4390
- // know one. These don't have to be accurate -- the result of them
4391
- // being wrong would just be a slight flicker on the first wheel
4392
- // scroll (if it is large enough).
4393
- if (ie) { wheelPixelsPerUnit = -.53; }
4394
- else if (gecko) { wheelPixelsPerUnit = 15; }
4395
- else if (chrome) { wheelPixelsPerUnit = -.7; }
4396
- else if (safari) { wheelPixelsPerUnit = -1/3; }
4397
 
4398
- function wheelEventDelta(e) {
4399
- var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
4400
- if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail; }
4401
- if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail; }
4402
- else if (dy == null) { dy = e.wheelDelta; }
4403
- return {x: dx, y: dy}
4404
- }
4405
- function wheelEventPixels(e) {
4406
- var delta = wheelEventDelta(e);
4407
- delta.x *= wheelPixelsPerUnit;
4408
- delta.y *= wheelPixelsPerUnit;
4409
- return delta
4410
  }
4411
 
4412
- function onScrollWheel(cm, e) {
4413
- var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;
4414
-
4415
- var display = cm.display, scroll = display.scroller;
4416
- // Quit if there's nothing to scroll here
4417
- var canScrollX = scroll.scrollWidth > scroll.clientWidth;
4418
- var canScrollY = scroll.scrollHeight > scroll.clientHeight;
4419
- if (!(dx && canScrollX || dy && canScrollY)) { return }
4420
-
4421
- // Webkit browsers on OS X abort momentum scrolls when the target
4422
- // of the scroll event is removed from the scrollable element.
4423
- // This hack (see related code in patchDisplay) makes sure the
4424
- // element is kept around.
4425
- if (dy && mac && webkit) {
4426
- outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {
4427
- for (var i = 0; i < view.length; i++) {
4428
- if (view[i].node == cur) {
4429
- cm.display.currentWheelTarget = cur;
4430
- break outer
4431
- }
4432
- }
4433
  }
 
 
 
 
 
4434
  }
 
 
4435
 
4436
- // On some browsers, horizontal scrolling will cause redraws to
4437
- // happen before the gutter has been realigned, causing it to
4438
- // wriggle around in a most unseemly way. When we have an
4439
- // estimated pixels/delta value, we just handle horizontal
4440
- // scrolling entirely here. It'll be slightly off from native, but
4441
- // better than glitching out.
4442
- if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
4443
- if (dy && canScrollY)
4444
- { setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight))); }
4445
- setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
4446
- // Only prevent default scrolling if vertical scrolling is
4447
- // actually possible. Otherwise, it causes vertical scroll
4448
- // jitter on OSX trackpads when deltaX is small and deltaY
4449
- // is large (issue #3579)
4450
- if (!dy || (dy && canScrollY))
4451
- { e_preventDefault(e); }
4452
- display.wheelStartX = null; // Abort measurement, if in progress
4453
- return
 
 
 
 
 
 
4454
  }
4455
 
4456
- // 'Project' the visible viewport to cover the area that is being
4457
- // scrolled into view (if we know enough to estimate it).
4458
- if (dy && wheelPixelsPerUnit != null) {
4459
- var pixels = dy * wheelPixelsPerUnit;
4460
- var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
4461
- if (pixels < 0) { top = Math.max(0, top + pixels - 50); }
4462
- else { bot = Math.min(cm.doc.height, bot + pixels + 50); }
4463
- updateDisplaySimple(cm, {top: top, bottom: bot});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4464
  }
 
 
4465
 
4466
- if (wheelSamples < 20) {
4467
- if (display.wheelStartX == null) {
4468
- display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
4469
- display.wheelDX = dx; display.wheelDY = dy;
4470
- setTimeout(function () {
4471
- if (display.wheelStartX == null) { return }
4472
- var movedX = scroll.scrollLeft - display.wheelStartX;
4473
- var movedY = scroll.scrollTop - display.wheelStartY;
4474
- var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
4475
- (movedX && display.wheelDX && movedX / display.wheelDX);
4476
- display.wheelStartX = display.wheelStartY = null;
4477
- if (!sample) { return }
4478
- wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
4479
- ++wheelSamples;
4480
- }, 200);
4481
- } else {
4482
- display.wheelDX += dx; display.wheelDY += dy;
4483
- }
 
 
 
4484
  }
4485
  }
4486
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4487
  // SCROLLBARS
4488
 
4489
  // Prepare DOM reads needed to update the scrollbars. Done in one
@@ -4660,139 +4696,12 @@ webpackJsonp([2],{
4660
  node.setAttribute("cm-not-content", "true");
4661
  }, function (pos, axis) {
4662
  if (axis == "horizontal") { setScrollLeft(cm, pos); }
4663
- else { setScrollTop(cm, pos); }
4664
  }, cm);
4665
  if (cm.display.scrollbars.addClass)
4666
  { addClass(cm.display.wrapper, cm.display.scrollbars.addClass); }
4667
  }
4668
 
4669
- // SCROLLING THINGS INTO VIEW
4670
-
4671
- // If an editor sits on the top or bottom of the window, partially
4672
- // scrolled out of view, this ensures that the cursor is visible.
4673
- function maybeScrollWindow(cm, rect) {
4674
- if (signalDOMEvent(cm, "scrollCursorIntoView")) { return }
4675
-
4676
- var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
4677
- if (rect.top + box.top < 0) { doScroll = true; }
4678
- else if (rect.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { doScroll = false; }
4679
- if (doScroll != null && !phantom) {
4680
- var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n top: " + (rect.top - display.viewOffset - paddingTop(cm.display)) + "px;\n height: " + (rect.bottom - rect.top + scrollGap(cm) + display.barHeight) + "px;\n left: " + (rect.left) + "px; width: " + (Math.max(2, rect.right - rect.left)) + "px;"));
4681
- cm.display.lineSpace.appendChild(scrollNode);
4682
- scrollNode.scrollIntoView(doScroll);
4683
- cm.display.lineSpace.removeChild(scrollNode);
4684
- }
4685
- }
4686
-
4687
- // Scroll a given position into view (immediately), verifying that
4688
- // it actually became visible (as line heights are accurately
4689
- // measured, the position of something may 'drift' during drawing).
4690
- function scrollPosIntoView(cm, pos, end, margin) {
4691
- if (margin == null) { margin = 0; }
4692
- var rect;
4693
- for (var limit = 0; limit < 5; limit++) {
4694
- var changed = false;
4695
- var coords = cursorCoords(cm, pos);
4696
- var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
4697
- rect = {left: Math.min(coords.left, endCoords.left),
4698
- top: Math.min(coords.top, endCoords.top) - margin,
4699
- right: Math.max(coords.left, endCoords.left),
4700
- bottom: Math.max(coords.bottom, endCoords.bottom) + margin};
4701
- var scrollPos = calculateScrollPos(cm, rect);
4702
- var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
4703
- if (scrollPos.scrollTop != null) {
4704
- setScrollTop(cm, scrollPos.scrollTop);
4705
- if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true; }
4706
- }
4707
- if (scrollPos.scrollLeft != null) {
4708
- setScrollLeft(cm, scrollPos.scrollLeft);
4709
- if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true; }
4710
- }
4711
- if (!changed) { break }
4712
- }
4713
- return rect
4714
- }
4715
-
4716
- // Scroll a given set of coordinates into view (immediately).
4717
- function scrollIntoView(cm, rect) {
4718
- var scrollPos = calculateScrollPos(cm, rect);
4719
- if (scrollPos.scrollTop != null) { setScrollTop(cm, scrollPos.scrollTop); }
4720
- if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft); }
4721
- }
4722
-
4723
- // Calculate a new scroll position needed to scroll the given
4724
- // rectangle into view. Returns an object with scrollTop and
4725
- // scrollLeft properties. When these are undefined, the
4726
- // vertical/horizontal position does not need to be adjusted.
4727
- function calculateScrollPos(cm, rect) {
4728
- var display = cm.display, snapMargin = textHeight(cm.display);
4729
- if (rect.top < 0) { rect.top = 0; }
4730
- var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;
4731
- var screen = displayHeight(cm), result = {};
4732
- if (rect.bottom - rect.top > screen) { rect.bottom = rect.top + screen; }
4733
- var docBottom = cm.doc.height + paddingVert(display);
4734
- var atTop = rect.top < snapMargin, atBottom = rect.bottom > docBottom - snapMargin;
4735
- if (rect.top < screentop) {
4736
- result.scrollTop = atTop ? 0 : rect.top;
4737
- } else if (rect.bottom > screentop + screen) {
4738
- var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen);
4739
- if (newTop != screentop) { result.scrollTop = newTop; }
4740
- }
4741
-
4742
- var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;
4743
- var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0);
4744
- var tooWide = rect.right - rect.left > screenw;
4745
- if (tooWide) { rect.right = rect.left + screenw; }
4746
- if (rect.left < 10)
4747
- { result.scrollLeft = 0; }
4748
- else if (rect.left < screenleft)
4749
- { result.scrollLeft = Math.max(0, rect.left - (tooWide ? 0 : 10)); }
4750
- else if (rect.right > screenw + screenleft - 3)
4751
- { result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw; }
4752
- return result
4753
- }
4754
-
4755
- // Store a relative adjustment to the scroll position in the current
4756
- // operation (to be applied when the operation finishes).
4757
- function addToScrollPos(cm, left, top) {
4758
- if (left != null || top != null) { resolveScrollToPos(cm); }
4759
- if (left != null)
4760
- { cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left; }
4761
- if (top != null)
4762
- { cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top; }
4763
- }
4764
-
4765
- // Make sure that at the end of the operation the current cursor is
4766
- // shown.
4767
- function ensureCursorVisible(cm) {
4768
- resolveScrollToPos(cm);
4769
- var cur = cm.getCursor(), from = cur, to = cur;
4770
- if (!cm.options.lineWrapping) {
4771
- from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur;
4772
- to = Pos(cur.line, cur.ch + 1);
4773
- }
4774
- cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin};
4775
- }
4776
-
4777
- // When an operation has its scrollToPos property set, and another
4778
- // scroll action is applied before the end of the operation, this
4779
- // 'simulates' scrolling that position into view in a cheap way, so
4780
- // that the effect of intermediate scroll commands is not ignored.
4781
- function resolveScrollToPos(cm) {
4782
- var range$$1 = cm.curOp.scrollToPos;
4783
- if (range$$1) {
4784
- cm.curOp.scrollToPos = null;
4785
- var from = estimateCoords(cm, range$$1.from), to = estimateCoords(cm, range$$1.to);
4786
- var sPos = calculateScrollPos(cm, {
4787
- left: Math.min(from.left, to.left),
4788
- top: Math.min(from.top, to.top) - range$$1.margin,
4789
- right: Math.max(from.right, to.right),
4790
- bottom: Math.max(from.bottom, to.bottom) + range$$1.margin
4791
- });
4792
- cm.scrollTo(sPos.scrollLeft, sPos.scrollTop);
4793
- }
4794
- }
4795
-
4796
  // Operations are used to wrap a series of changes to the editor
4797
  // state in such a way that each change won't have to update the
4798
  // cursor and display (which would be awkward, slow, and
@@ -4921,17 +4830,9 @@ webpackJsonp([2],{
4921
  { display.wheelStartX = display.wheelStartY = null; }
4922
 
4923
  // Propagate the scroll position to the actual DOM scroller
4924
- if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) {
4925
- doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop));
4926
- display.scrollbars.setScrollTop(doc.scrollTop);
4927
- display.scroller.scrollTop = doc.scrollTop;
4928
- }
4929
- if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) {
4930
- doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, op.scrollLeft));
4931
- display.scrollbars.setScrollLeft(doc.scrollLeft);
4932
- display.scroller.scrollLeft = doc.scrollLeft;
4933
- alignHorizontally(cm);
4934
- }
4935
  // If we need to scroll a specific position into view, do so.
4936
  if (op.scrollToPos) {
4937
  var rect = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),
@@ -5225,6 +5126,36 @@ webpackJsonp([2],{
5225
  }
5226
  }
5227
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5228
  // Does the actual updating of the line display. Bails out
5229
  // (returning false) when there is nothing to be done and forced is
5230
  // false.
@@ -5274,14 +5205,14 @@ webpackJsonp([2],{
5274
 
5275
  // For big changes, we hide the enclosing element during the
5276
  // update, since that speeds up the operations on most browsers.
5277
- var focused = activeElt();
5278
  if (toUpdate > 4) { display.lineDiv.style.display = "none"; }
5279
  patchDisplay(cm, display.updateLineNumbers, update.dims);
5280
  if (toUpdate > 4) { display.lineDiv.style.display = ""; }
5281
  display.renderedView = display.view;
5282
  // There might have been a widget with a focused element that got
5283
  // hidden or updated, if so re-focus it.
5284
- if (focused && activeElt() != focused && focused.offsetHeight) { focused.focus(); }
5285
 
5286
  // Prevent selection and cursors from interfering with the scroll
5287
  // width and height.
@@ -5429,6 +5360,117 @@ webpackJsonp([2],{
5429
  }
5430
  }
5431
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5432
  // Selection objects are immutable. A new one is created every time
5433
  // the selection changes. A selection is one or more non-overlapping
5434
  // (and non-touching) ranges, sorted, and an integer that indicates
@@ -6025,7 +6067,7 @@ webpackJsonp([2],{
6025
  // Verify that the selection does not partially select any atomic
6026
  // marked ranges.
6027
  function reCheckSelection(doc) {
6028
- setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll);
6029
  }
6030
 
6031
  // Return a selection that does not partially select any atomic
@@ -6653,7 +6695,7 @@ webpackJsonp([2],{
6653
 
6654
  function adjustScrollWhenAboveVisible(cm, line, diff) {
6655
  if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))
6656
- { addToScrollPos(cm, null, diff); }
6657
  }
6658
 
6659
  function addLineWidget(doc, handle, node, options) {
@@ -6668,7 +6710,7 @@ webpackJsonp([2],{
6668
  if (cm && !lineIsHidden(doc, line)) {
6669
  var aboveVisible = heightAtLine(line) < doc.scrollTop;
6670
  updateLineHeight(line, line.height + widgetHeight(widget));
6671
- if (aboveVisible) { addToScrollPos(cm, null, widget.height); }
6672
  cm.curOp.forceUpdate = true;
6673
  }
6674
  return true
@@ -7016,7 +7058,7 @@ webpackJsonp([2],{
7016
  var top = Pos(this.first, 0), last = this.first + this.size - 1;
7017
  makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
7018
  text: this.splitLines(code), origin: "setValue", full: true}, true);
7019
- if (this.cm) { this.cm.scrollTo(0, 0); }
7020
  setSelection(this, simpleSelection(top), sel_dontScroll);
7021
  }),
7022
  replaceRange: function(code, from, to, origin) {
@@ -8661,7 +8703,7 @@ webpackJsonp([2],{
8661
  // area, ensure viewport is updated when scrolling.
8662
  on(d.scroller, "scroll", function () {
8663
  if (d.scroller.clientHeight) {
8664
- setScrollTop(cm, d.scroller.scrollTop);
8665
  setScrollLeft(cm, d.scroller.scrollLeft, true);
8666
  signal(cm, "scroll", cm);
8667
  }
@@ -9194,7 +9236,7 @@ webpackJsonp([2],{
9194
  goals.push(headPos.left);
9195
  var pos = findPosV(this$1, headPos, dir, unit);
9196
  if (unit == "page" && range$$1 == doc.sel.primary())
9197
- { addToScrollPos(this$1, null, charCoords(this$1, pos, "div").top - headPos.top); }
9198
  return pos
9199
  }, sel_move);
9200
  if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++)
@@ -9231,11 +9273,7 @@ webpackJsonp([2],{
9231
  hasFocus: function() { return this.display.input.getField() == activeElt() },
9232
  isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) },
9233
 
9234
- scrollTo: methodOp(function(x, y) {
9235
- if (x != null || y != null) { resolveScrollToPos(this); }
9236
- if (x != null) { this.curOp.scrollLeft = x; }
9237
- if (y != null) { this.curOp.scrollTop = y; }
9238
- }),
9239
  getScrollInfo: function() {
9240
  var scroller = this.display.scroller;
9241
  return {left: scroller.scrollLeft, top: scroller.scrollTop,
@@ -9257,16 +9295,9 @@ webpackJsonp([2],{
9257
  range$$1.margin = margin || 0;
9258
 
9259
  if (range$$1.from.line != null) {
9260
- resolveScrollToPos(this);
9261
- this.curOp.scrollToPos = range$$1;
9262
  } else {
9263
- var sPos = calculateScrollPos(this, {
9264
- left: Math.min(range$$1.from.left, range$$1.to.left),
9265
- top: Math.min(range$$1.from.top, range$$1.to.top) - range$$1.margin,
9266
- right: Math.max(range$$1.from.right, range$$1.to.right),
9267
- bottom: Math.max(range$$1.from.bottom, range$$1.to.bottom) + range$$1.margin
9268
- });
9269
- this.scrollTo(sPos.scrollLeft, sPos.scrollTop);
9270
  }
9271
  }),
9272
 
@@ -9294,7 +9325,7 @@ webpackJsonp([2],{
9294
  regChange(this);
9295
  this.curOp.forceUpdate = true;
9296
  clearCaches(this);
9297
- this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop);
9298
  updateGutterSpace(this);
9299
  if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)
9300
  { estimateLineHeights(this); }
@@ -9307,7 +9338,7 @@ webpackJsonp([2],{
9307
  attachDoc(this, doc);
9308
  clearCaches(this);
9309
  this.display.input.reset();
9310
- this.scrollTo(doc.scrollLeft, doc.scrollTop);
9311
  this.curOp.forceScroll = true;
9312
  signalLater(this, "swapDoc", this, old);
9313
  return old
@@ -10062,7 +10093,7 @@ webpackJsonp([2],{
10062
  // Reset the input to correspond to the selection (or to be empty,
10063
  // when not typing and nothing is selected)
10064
  TextareaInput.prototype.reset = function (typing) {
10065
- if (this.contextMenuPending) { return }
10066
  var minimal, selected, cm = this.cm, doc = cm.doc;
10067
  if (cm.somethingSelected()) {
10068
  this.prevInput = "";
@@ -10427,7 +10458,7 @@ webpackJsonp([2],{
10427
 
10428
  addLegacyProps(CodeMirror$1);
10429
 
10430
- CodeMirror$1.version = "5.25.2";
10431
 
10432
  return CodeMirror$1;
10433
 
@@ -10842,7 +10873,6 @@ webpackJsonp([2],{
10842
  ch == "{" && (cx.type == "at" || cx.type == "atBlock")) {
10843
  // Dedent relative to current context.
10844
  indent = Math.max(0, cx.indent - indentUnit);
10845
- cx = cx.prev;
10846
  }
10847
  }
10848
  return indent;
@@ -10913,7 +10943,7 @@ webpackJsonp([2],{
10913
  "border-top-left-radius", "border-top-right-radius", "border-top-style",
10914
  "border-top-width", "border-width", "bottom", "box-decoration-break",
10915
  "box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
10916
- "caption-side", "clear", "clip", "color", "color-profile", "column-count",
10917
  "column-fill", "column-gap", "column-rule", "column-rule-color",
10918
  "column-rule-style", "column-rule-width", "column-span", "column-width",
10919
  "columns", "content", "counter-increment", "counter-reset", "crop", "cue",
@@ -10934,7 +10964,7 @@ webpackJsonp([2],{
10934
  "grid-row-start", "grid-template", "grid-template-areas", "grid-template-columns",
10935
  "grid-template-rows", "hanging-punctuation", "height", "hyphens",
10936
  "icon", "image-orientation", "image-rendering", "image-resolution",
10937
- "inline-box-align", "justify-content", "left", "letter-spacing",
10938
  "line-break", "line-height", "line-stacking", "line-stacking-ruby",
10939
  "line-stacking-shift", "line-stacking-strategy", "list-style",
10940
  "list-style-image", "list-style-position", "list-style-type", "margin",
@@ -10949,7 +10979,7 @@ webpackJsonp([2],{
10949
  "padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
10950
  "page", "page-break-after", "page-break-before", "page-break-inside",
10951
  "page-policy", "pause", "pause-after", "pause-before", "perspective",
10952
- "perspective-origin", "pitch", "pitch-range", "play-during", "position",
10953
  "presentation-level", "punctuation-trim", "quotes", "region-break-after",
10954
  "region-break-before", "region-break-inside", "region-fragment",
10955
  "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
@@ -11100,13 +11130,13 @@ webpackJsonp([2],{
11100
  "s-resize", "sans-serif", "saturation", "scale", "scale3d", "scaleX", "scaleY", "scaleZ", "screen",
11101
  "scroll", "scrollbar", "scroll-position", "se-resize", "searchfield",
11102
  "searchfield-cancel-button", "searchfield-decoration",
11103
- "searchfield-results-button", "searchfield-results-decoration",
11104
  "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
11105
  "simp-chinese-formal", "simp-chinese-informal", "single",
11106
  "skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
11107
  "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
11108
  "small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali",
11109
- "source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "spell-out", "square",
11110
  "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub",
11111
  "subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "system-ui", "table",
11112
  "table-caption", "table-cell", "table-column", "table-column-group",
2236
  ch = dir < 0 ? lineObj.text.length - 1 : 0;
2237
  var targetTop = measureCharPrepared(cm, prep, ch).top;
2238
  ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch);
2239
+ if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1); }
2240
  } else { ch = dir < 0 ? part.to : part.from; }
2241
  return new Pos(lineNo, ch, sticky)
2242
  }
4250
  setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false; } }, 150);
4251
  }
4252
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4253
  // Read the actual heights of the rendered lines, and update their
4254
  // stored heights to match.
4255
  function updateHeightsInViewport(cm) {
4308
  return {from: from, to: Math.max(to, from + 1)}
4309
  }
4310
 
4311
+ // Re-align line numbers and gutter marks to compensate for
4312
+ // horizontal scrolling.
4313
+ function alignHorizontally(cm) {
4314
+ var display = cm.display, view = display.view;
4315
+ if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return }
4316
+ var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
4317
+ var gutterW = display.gutters.offsetWidth, left = comp + "px";
4318
+ for (var i = 0; i < view.length; i++) { if (!view[i].hidden) {
4319
+ if (cm.options.fixedGutter) {
4320
+ if (view[i].gutter)
4321
+ { view[i].gutter.style.left = left; }
4322
+ if (view[i].gutterBackground)
4323
+ { view[i].gutterBackground.style.left = left; }
4324
+ }
4325
+ var align = view[i].alignable;
4326
+ if (align) { for (var j = 0; j < align.length; j++)
4327
+ { align[j].style.left = left; } }
4328
+ } }
4329
+ if (cm.options.fixedGutter)
4330
+ { display.gutters.style.left = (comp + gutterW) + "px"; }
4331
  }
4332
+
4333
+ // Used to ensure that the line number gutter is still the right
4334
+ // size for the current document size. Returns true when an update
4335
+ // is needed.
4336
+ function maybeUpdateLineNumberWidth(cm) {
4337
+ if (!cm.options.lineNumbers) { return false }
4338
+ var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
4339
+ if (last.length != display.lineNumChars) {
4340
+ var test = display.measure.appendChild(elt("div", [elt("div", last)],
4341
+ "CodeMirror-linenumber CodeMirror-gutter-elt"));
4342
+ var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
4343
+ display.lineGutter.style.width = "";
4344
+ display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1;
4345
+ display.lineNumWidth = display.lineNumInnerWidth + padding;
4346
+ display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
4347
+ display.lineGutter.style.width = display.lineNumWidth + "px";
4348
+ updateGutterSpace(cm);
4349
+ return true
4350
+ }
4351
+ return false
4352
  }
4353
 
4354
+ // SCROLLING THINGS INTO VIEW
 
 
 
 
 
 
 
 
 
4355
 
4356
+ // If an editor sits on the top or bottom of the window, partially
4357
+ // scrolled out of view, this ensures that the cursor is visible.
4358
+ function maybeScrollWindow(cm, rect) {
4359
+ if (signalDOMEvent(cm, "scrollCursorIntoView")) { return }
 
 
 
 
 
 
4360
 
4361
+ var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
4362
+ if (rect.top + box.top < 0) { doScroll = true; }
4363
+ else if (rect.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { doScroll = false; }
4364
+ if (doScroll != null && !phantom) {
4365
+ var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n top: " + (rect.top - display.viewOffset - paddingTop(cm.display)) + "px;\n height: " + (rect.bottom - rect.top + scrollGap(cm) + display.barHeight) + "px;\n left: " + (rect.left) + "px; width: " + (Math.max(2, rect.right - rect.left)) + "px;"));
4366
+ cm.display.lineSpace.appendChild(scrollNode);
4367
+ scrollNode.scrollIntoView(doScroll);
4368
+ cm.display.lineSpace.removeChild(scrollNode);
4369
+ }
 
 
 
4370
  }
4371
 
4372
+ // Scroll a given position into view (immediately), verifying that
4373
+ // it actually became visible (as line heights are accurately
4374
+ // measured, the position of something may 'drift' during drawing).
4375
+ function scrollPosIntoView(cm, pos, end, margin) {
4376
+ if (margin == null) { margin = 0; }
4377
+ var rect;
4378
+ for (var limit = 0; limit < 5; limit++) {
4379
+ var changed = false;
4380
+ var coords = cursorCoords(cm, pos);
4381
+ var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
4382
+ rect = {left: Math.min(coords.left, endCoords.left),
4383
+ top: Math.min(coords.top, endCoords.top) - margin,
4384
+ right: Math.max(coords.left, endCoords.left),
4385
+ bottom: Math.max(coords.bottom, endCoords.bottom) + margin};
4386
+ var scrollPos = calculateScrollPos(cm, rect);
4387
+ var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
4388
+ if (scrollPos.scrollTop != null) {
4389
+ updateScrollTop(cm, scrollPos.scrollTop);
4390
+ if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true; }
 
 
4391
  }
4392
+ if (scrollPos.scrollLeft != null) {
4393
+ setScrollLeft(cm, scrollPos.scrollLeft);
4394
+ if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true; }
4395
+ }
4396
+ if (!changed) { break }
4397
  }
4398
+ return rect
4399
+ }
4400
 
4401
+ // Scroll a given set of coordinates into view (immediately).
4402
+ function scrollIntoView(cm, rect) {
4403
+ var scrollPos = calculateScrollPos(cm, rect);
4404
+ if (scrollPos.scrollTop != null) { updateScrollTop(cm, scrollPos.scrollTop); }
4405
+ if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft); }
4406
+ }
4407
+
4408
+ // Calculate a new scroll position needed to scroll the given
4409
+ // rectangle into view. Returns an object with scrollTop and
4410
+ // scrollLeft properties. When these are undefined, the
4411
+ // vertical/horizontal position does not need to be adjusted.
4412
+ function calculateScrollPos(cm, rect) {
4413
+ var display = cm.display, snapMargin = textHeight(cm.display);
4414
+ if (rect.top < 0) { rect.top = 0; }
4415
+ var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;
4416
+ var screen = displayHeight(cm), result = {};
4417
+ if (rect.bottom - rect.top > screen) { rect.bottom = rect.top + screen; }
4418
+ var docBottom = cm.doc.height + paddingVert(display);
4419
+ var atTop = rect.top < snapMargin, atBottom = rect.bottom > docBottom - snapMargin;
4420
+ if (rect.top < screentop) {
4421
+ result.scrollTop = atTop ? 0 : rect.top;
4422
+ } else if (rect.bottom > screentop + screen) {
4423
+ var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen);
4424
+ if (newTop != screentop) { result.scrollTop = newTop; }
4425
  }
4426
 
4427
+ var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;
4428
+ var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0);
4429
+ var tooWide = rect.right - rect.left > screenw;
4430
+ if (tooWide) { rect.right = rect.left + screenw; }
4431
+ if (rect.left < 10)
4432
+ { result.scrollLeft = 0; }
4433
+ else if (rect.left < screenleft)
4434
+ { result.scrollLeft = Math.max(0, rect.left - (tooWide ? 0 : 10)); }
4435
+ else if (rect.right > screenw + screenleft - 3)
4436
+ { result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw; }
4437
+ return result
4438
+ }
4439
+
4440
+ // Store a relative adjustment to the scroll position in the current
4441
+ // operation (to be applied when the operation finishes).
4442
+ function addToScrollTop(cm, top) {
4443
+ if (top == null) { return }
4444
+ resolveScrollToPos(cm);
4445
+ cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top;
4446
+ }
4447
+
4448
+ // Make sure that at the end of the operation the current cursor is
4449
+ // shown.
4450
+ function ensureCursorVisible(cm) {
4451
+ resolveScrollToPos(cm);
4452
+ var cur = cm.getCursor(), from = cur, to = cur;
4453
+ if (!cm.options.lineWrapping) {
4454
+ from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur;
4455
+ to = Pos(cur.line, cur.ch + 1);
4456
  }
4457
+ cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin};
4458
+ }
4459
 
4460
+ function scrollToCoords(cm, x, y) {
4461
+ if (x != null || y != null) { resolveScrollToPos(cm); }
4462
+ if (x != null) { cm.curOp.scrollLeft = x; }
4463
+ if (y != null) { cm.curOp.scrollTop = y; }
4464
+ }
4465
+
4466
+ function scrollToRange(cm, range$$1) {
4467
+ resolveScrollToPos(cm);
4468
+ cm.curOp.scrollToPos = range$$1;
4469
+ }
4470
+
4471
+ // When an operation has its scrollToPos property set, and another
4472
+ // scroll action is applied before the end of the operation, this
4473
+ // 'simulates' scrolling that position into view in a cheap way, so
4474
+ // that the effect of intermediate scroll commands is not ignored.
4475
+ function resolveScrollToPos(cm) {
4476
+ var range$$1 = cm.curOp.scrollToPos;
4477
+ if (range$$1) {
4478
+ cm.curOp.scrollToPos = null;
4479
+ var from = estimateCoords(cm, range$$1.from), to = estimateCoords(cm, range$$1.to);
4480
+ scrollToCoordsRange(cm, from, to, range$$1.margin);
4481
  }
4482
  }
4483
 
4484
+ function scrollToCoordsRange(cm, from, to, margin) {
4485
+ var sPos = calculateScrollPos(cm, {
4486
+ left: Math.min(from.left, to.left),
4487
+ top: Math.min(from.top, to.top) - margin,
4488
+ right: Math.max(from.right, to.right),
4489
+ bottom: Math.max(from.bottom, to.bottom) + margin
4490
+ });
4491
+ scrollToCoords(cm, sPos.scrollLeft, sPos.scrollTop);
4492
+ }
4493
+
4494
+ // Sync the scrollable area and scrollbars, ensure the viewport
4495
+ // covers the visible area.
4496
+ function updateScrollTop(cm, val) {
4497
+ if (Math.abs(cm.doc.scrollTop - val) < 2) { return }
4498
+ if (!gecko) { updateDisplaySimple(cm, {top: val}); }
4499
+ setScrollTop(cm, val, true);
4500
+ if (gecko) { updateDisplaySimple(cm); }
4501
+ startWorker(cm, 100);
4502
+ }
4503
+
4504
+ function setScrollTop(cm, val, forceScroll) {
4505
+ val = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, val);
4506
+ if (cm.display.scroller.scrollTop == val && !forceScroll) { return }
4507
+ cm.doc.scrollTop = val;
4508
+ cm.display.scrollbars.setScrollTop(val);
4509
+ if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val; }
4510
+ }
4511
+
4512
+ // Sync scroller and scrollbar, ensure the gutter elements are
4513
+ // aligned.
4514
+ function setScrollLeft(cm, val, isScroller, forceScroll) {
4515
+ val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
4516
+ if ((isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) && !forceScroll) { return }
4517
+ cm.doc.scrollLeft = val;
4518
+ alignHorizontally(cm);
4519
+ if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val; }
4520
+ cm.display.scrollbars.setScrollLeft(val);
4521
+ }
4522
+
4523
  // SCROLLBARS
4524
 
4525
  // Prepare DOM reads needed to update the scrollbars. Done in one
4696
  node.setAttribute("cm-not-content", "true");
4697
  }, function (pos, axis) {
4698
  if (axis == "horizontal") { setScrollLeft(cm, pos); }
4699
+ else { updateScrollTop(cm, pos); }
4700
  }, cm);
4701
  if (cm.display.scrollbars.addClass)
4702
  { addClass(cm.display.wrapper, cm.display.scrollbars.addClass); }
4703
  }
4704
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4705
  // Operations are used to wrap a series of changes to the editor
4706
  // state in such a way that each change won't have to update the
4707
  // cursor and display (which would be awkward, slow, and
4830
  { display.wheelStartX = display.wheelStartY = null; }
4831
 
4832
  // Propagate the scroll position to the actual DOM scroller
4833
+ if (op.scrollTop != null) { setScrollTop(cm, op.scrollTop, op.forceScroll); }
4834
+
4835
+ if (op.scrollLeft != null) { setScrollLeft(cm, op.scrollLeft, true, true); }
 
 
 
 
 
 
 
 
4836
  // If we need to scroll a specific position into view, do so.
4837
  if (op.scrollToPos) {
4838
  var rect = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),
5126
  }
5127
  }
5128
 
5129
+ function selectionSnapshot(cm) {
5130
+ if (cm.hasFocus()) { return null }
5131
+ var active = activeElt();
5132
+ if (!active || !contains(cm.display.lineDiv, active)) { return null }
5133
+ var result = {activeElt: active};
5134
+ if (window.getSelection) {
5135
+ var sel = window.getSelection();
5136
+ if (sel.anchorNode && sel.extend && contains(cm.display.lineDiv, sel.anchorNode)) {
5137
+ result.anchorNode = sel.anchorNode;
5138
+ result.anchorOffset = sel.anchorOffset;
5139
+ result.focusNode = sel.focusNode;
5140
+ result.focusOffset = sel.focusOffset;
5141
+ }
5142
+ }
5143
+ return result
5144
+ }
5145
+
5146
+ function restoreSelection(snapshot) {
5147
+ if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt()) { return }
5148
+ snapshot.activeElt.focus();
5149
+ if (snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) {
5150
+ var sel = window.getSelection(), range$$1 = document.createRange();
5151
+ range$$1.setEnd(snapshot.anchorNode, snapshot.anchorOffset);
5152
+ range$$1.collapse(false);
5153
+ sel.removeAllRanges();
5154
+ sel.addRange(range$$1);
5155
+ sel.extend(snapshot.focusNode, snapshot.focusOffset);
5156
+ }
5157
+ }
5158
+
5159
  // Does the actual updating of the line display. Bails out
5160
  // (returning false) when there is nothing to be done and forced is
5161
  // false.
5205
 
5206
  // For big changes, we hide the enclosing element during the
5207
  // update, since that speeds up the operations on most browsers.
5208
+ var selSnapshot = selectionSnapshot(cm);
5209
  if (toUpdate > 4) { display.lineDiv.style.display = "none"; }
5210
  patchDisplay(cm, display.updateLineNumbers, update.dims);
5211
  if (toUpdate > 4) { display.lineDiv.style.display = ""; }
5212
  display.renderedView = display.view;
5213
  // There might have been a widget with a focused element that got
5214
  // hidden or updated, if so re-focus it.
5215
+ restoreSelection(selSnapshot);
5216
 
5217
  // Prevent selection and cursors from interfering with the scroll
5218
  // width and height.
5360
  }
5361
  }
5362
 
5363
+ // Since the delta values reported on mouse wheel events are
5364
+ // unstandardized between browsers and even browser versions, and
5365
+ // generally horribly unpredictable, this code starts by measuring
5366
+ // the scroll effect that the first few mouse wheel events have,
5367
+ // and, from that, detects the way it can convert deltas to pixel
5368
+ // offsets afterwards.
5369
+ //
5370
+ // The reason we want to know the amount a wheel event will scroll
5371
+ // is that it gives us a chance to update the display before the
5372
+ // actual scrolling happens, reducing flickering.
5373
+
5374
+ var wheelSamples = 0;
5375
+ var wheelPixelsPerUnit = null;
5376
+ // Fill in a browser-detected starting value on browsers where we
5377
+ // know one. These don't have to be accurate -- the result of them
5378
+ // being wrong would just be a slight flicker on the first wheel
5379
+ // scroll (if it is large enough).
5380
+ if (ie) { wheelPixelsPerUnit = -.53; }
5381
+ else if (gecko) { wheelPixelsPerUnit = 15; }
5382
+ else if (chrome) { wheelPixelsPerUnit = -.7; }
5383
+ else if (safari) { wheelPixelsPerUnit = -1/3; }
5384
+
5385
+ function wheelEventDelta(e) {
5386
+ var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
5387
+ if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail; }
5388
+ if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail; }
5389
+ else if (dy == null) { dy = e.wheelDelta; }
5390
+ return {x: dx, y: dy}
5391
+ }
5392
+ function wheelEventPixels(e) {
5393
+ var delta = wheelEventDelta(e);
5394
+ delta.x *= wheelPixelsPerUnit;
5395
+ delta.y *= wheelPixelsPerUnit;
5396
+ return delta
5397
+ }
5398
+
5399
+ function onScrollWheel(cm, e) {
5400
+ var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;
5401
+
5402
+ var display = cm.display, scroll = display.scroller;
5403
+ // Quit if there's nothing to scroll here
5404
+ var canScrollX = scroll.scrollWidth > scroll.clientWidth;
5405
+ var canScrollY = scroll.scrollHeight > scroll.clientHeight;
5406
+ if (!(dx && canScrollX || dy && canScrollY)) { return }
5407
+
5408
+ // Webkit browsers on OS X abort momentum scrolls when the target
5409
+ // of the scroll event is removed from the scrollable element.
5410
+ // This hack (see related code in patchDisplay) makes sure the
5411
+ // element is kept around.
5412
+ if (dy && mac && webkit) {
5413
+ outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {
5414
+ for (var i = 0; i < view.length; i++) {
5415
+ if (view[i].node == cur) {
5416
+ cm.display.currentWheelTarget = cur;
5417
+ break outer
5418
+ }
5419
+ }
5420
+ }
5421
+ }
5422
+
5423
+ // On some browsers, horizontal scrolling will cause redraws to
5424
+ // happen before the gutter has been realigned, causing it to
5425
+ // wriggle around in a most unseemly way. When we have an
5426
+ // estimated pixels/delta value, we just handle horizontal
5427
+ // scrolling entirely here. It'll be slightly off from native, but
5428
+ // better than glitching out.
5429
+ if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
5430
+ if (dy && canScrollY)
5431
+ { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * wheelPixelsPerUnit)); }
5432
+ setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * wheelPixelsPerUnit));
5433
+ // Only prevent default scrolling if vertical scrolling is
5434
+ // actually possible. Otherwise, it causes vertical scroll
5435
+ // jitter on OSX trackpads when deltaX is small and deltaY
5436
+ // is large (issue #3579)
5437
+ if (!dy || (dy && canScrollY))
5438
+ { e_preventDefault(e); }
5439
+ display.wheelStartX = null; // Abort measurement, if in progress
5440
+ return
5441
+ }
5442
+
5443
+ // 'Project' the visible viewport to cover the area that is being
5444
+ // scrolled into view (if we know enough to estimate it).
5445
+ if (dy && wheelPixelsPerUnit != null) {
5446
+ var pixels = dy * wheelPixelsPerUnit;
5447
+ var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
5448
+ if (pixels < 0) { top = Math.max(0, top + pixels - 50); }
5449
+ else { bot = Math.min(cm.doc.height, bot + pixels + 50); }
5450
+ updateDisplaySimple(cm, {top: top, bottom: bot});
5451
+ }
5452
+
5453
+ if (wheelSamples < 20) {
5454
+ if (display.wheelStartX == null) {
5455
+ display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
5456
+ display.wheelDX = dx; display.wheelDY = dy;
5457
+ setTimeout(function () {
5458
+ if (display.wheelStartX == null) { return }
5459
+ var movedX = scroll.scrollLeft - display.wheelStartX;
5460
+ var movedY = scroll.scrollTop - display.wheelStartY;
5461
+ var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
5462
+ (movedX && display.wheelDX && movedX / display.wheelDX);
5463
+ display.wheelStartX = display.wheelStartY = null;
5464
+ if (!sample) { return }
5465
+ wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
5466
+ ++wheelSamples;
5467
+ }, 200);
5468
+ } else {
5469
+ display.wheelDX += dx; display.wheelDY += dy;
5470
+ }
5471
+ }
5472
+ }
5473
+
5474
  // Selection objects are immutable. A new one is created every time
5475
  // the selection changes. A selection is one or more non-overlapping
5476
  // (and non-touching) ranges, sorted, and an integer that indicates
6067
  // Verify that the selection does not partially select any atomic
6068
  // marked ranges.
6069
  function reCheckSelection(doc) {
6070
+ setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false));
6071
  }
6072
 
6073
  // Return a selection that does not partially select any atomic
6695
 
6696
  function adjustScrollWhenAboveVisible(cm, line, diff) {
6697
  if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))
6698
+ { addToScrollTop(cm, diff); }
6699
  }
6700
 
6701
  function addLineWidget(doc, handle, node, options) {
6710
  if (cm && !lineIsHidden(doc, line)) {
6711
  var aboveVisible = heightAtLine(line) < doc.scrollTop;
6712
  updateLineHeight(line, line.height + widgetHeight(widget));
6713
+ if (aboveVisible) { addToScrollTop(cm, widget.height); }
6714
  cm.curOp.forceUpdate = true;
6715
  }
6716
  return true
7058
  var top = Pos(this.first, 0), last = this.first + this.size - 1;
7059
  makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
7060
  text: this.splitLines(code), origin: "setValue", full: true}, true);
7061
+ if (this.cm) { scrollToCoords(this.cm, 0, 0); }
7062
  setSelection(this, simpleSelection(top), sel_dontScroll);
7063
  }),
7064
  replaceRange: function(code, from, to, origin) {
8703
  // area, ensure viewport is updated when scrolling.
8704
  on(d.scroller, "scroll", function () {
8705
  if (d.scroller.clientHeight) {
8706
+ updateScrollTop(cm, d.scroller.scrollTop);
8707
  setScrollLeft(cm, d.scroller.scrollLeft, true);
8708
  signal(cm, "scroll", cm);
8709
  }
9236
  goals.push(headPos.left);
9237
  var pos = findPosV(this$1, headPos, dir, unit);
9238
  if (unit == "page" && range$$1 == doc.sel.primary())
9239
+ { addToScrollTop(this$1, charCoords(this$1, pos, "div").top - headPos.top); }
9240
  return pos
9241
  }, sel_move);
9242
  if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++)
9273
  hasFocus: function() { return this.display.input.getField() == activeElt() },
9274
  isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) },
9275
 
9276
+ scrollTo: methodOp(function (x, y) { scrollToCoords(this, x, y); }),
 
 
 
 
9277
  getScrollInfo: function() {
9278
  var scroller = this.display.scroller;
9279
  return {left: scroller.scrollLeft, top: scroller.scrollTop,
9295
  range$$1.margin = margin || 0;
9296
 
9297
  if (range$$1.from.line != null) {
9298
+ scrollToRange(this, range$$1);
 
9299
  } else {
9300
+ scrollToCoordsRange(this, range$$1.from, range$$1.to, range$$1.margin);
 
 
 
 
 
 
9301
  }
9302
  }),
9303
 
9325
  regChange(this);
9326
  this.curOp.forceUpdate = true;
9327
  clearCaches(this);
9328
+ scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop);
9329
  updateGutterSpace(this);
9330
  if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)
9331
  { estimateLineHeights(this); }
9338
  attachDoc(this, doc);
9339
  clearCaches(this);
9340
  this.display.input.reset();
9341
+ scrollToCoords(this, doc.scrollLeft, doc.scrollTop);
9342
  this.curOp.forceScroll = true;
9343
  signalLater(this, "swapDoc", this, old);
9344
  return old
10093
  // Reset the input to correspond to the selection (or to be empty,
10094
  // when not typing and nothing is selected)
10095
  TextareaInput.prototype.reset = function (typing) {
10096
+ if (this.contextMenuPending || this.composing) { return }
10097
  var minimal, selected, cm = this.cm, doc = cm.doc;
10098
  if (cm.somethingSelected()) {
10099
  this.prevInput = "";
10458
 
10459
  addLegacyProps(CodeMirror$1);
10460
 
10461
+ CodeMirror$1.version = "5.26.0";
10462
 
10463
  return CodeMirror$1;
10464
 
10873
  ch == "{" && (cx.type == "at" || cx.type == "atBlock")) {
10874
  // Dedent relative to current context.
10875
  indent = Math.max(0, cx.indent - indentUnit);
 
10876
  }
10877
  }
10878
  return indent;
10943
  "border-top-left-radius", "border-top-right-radius", "border-top-style",
10944
  "border-top-width", "border-width", "bottom", "box-decoration-break",
10945
  "box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
10946
+ "caption-side", "caret-color", "clear", "clip", "color", "color-profile", "column-count",
10947
  "column-fill", "column-gap", "column-rule", "column-rule-color",
10948
  "column-rule-style", "column-rule-width", "column-span", "column-width",
10949
  "columns", "content", "counter-increment", "counter-reset", "crop", "cue",
10964
  "grid-row-start", "grid-template", "grid-template-areas", "grid-template-columns",
10965
  "grid-template-rows", "hanging-punctuation", "height", "hyphens",
10966
  "icon", "image-orientation", "image-rendering", "image-resolution",
10967
+ "inline-box-align", "justify-content", "justify-items", "justify-self", "left", "letter-spacing",
10968
  "line-break", "line-height", "line-stacking", "line-stacking-ruby",
10969
  "line-stacking-shift", "line-stacking-strategy", "list-style",
10970
  "list-style-image", "list-style-position", "list-style-type", "margin",
10979
  "padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
10980
  "page", "page-break-after", "page-break-before", "page-break-inside",
10981
  "page-policy", "pause", "pause-after", "pause-before", "perspective",
10982
+ "perspective-origin", "pitch", "pitch-range", "place-content", "place-items", "place-self", "play-during", "position",
10983
  "presentation-level", "punctuation-trim", "quotes", "region-break-after",
10984
  "region-break-before", "region-break-inside", "region-fragment",
10985
  "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
11130
  "s-resize", "sans-serif", "saturation", "scale", "scale3d", "scaleX", "scaleY", "scaleZ", "screen",
11131
  "scroll", "scrollbar", "scroll-position", "se-resize", "searchfield",
11132
  "searchfield-cancel-button", "searchfield-decoration",
11133
+ "searchfield-results-button", "searchfield-results-decoration", "self-start", "self-end",
11134
  "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
11135
  "simp-chinese-formal", "simp-chinese-informal", "single",
11136
  "skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
11137
  "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
11138
  "small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali",
11139
+ "source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "space-evenly", "spell-out", "square",
11140
  "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub",
11141
  "subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "system-ui", "table",
11142
  "table-caption", "table-cell", "table-column", "table-column-group",
assets/js/mailpoet.js CHANGED
@@ -19057,7 +19057,7 @@ webpackJsonp([3],[
19057
 
19058
  /* WEBPACK VAR INJECTION */(function(global) {/*!
19059
  * Parsley.js
19060
- * Version 2.7.0 - built Wed, Mar 1st 2017, 3:53 pm
19061
  * http://parsleyjs.org
19062
  * Guillaume Potier - <guillaume@wisembly.com>
19063
  * Marc-Andre Lafortune - <petroselinum@marc-andre.ca>
@@ -19071,6 +19071,8 @@ webpackJsonp([3],[
19071
 
19072
  var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })();
19073
 
 
 
19074
  function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }
19075
 
19076
  (function (global, factory) {
@@ -19081,10 +19083,10 @@ webpackJsonp([3],[
19081
  var globalID = 1;
19082
  var pastWarnings = {};
19083
 
19084
- var Utils__Utils = {
19085
  // Parsley DOM-API
19086
  // returns object from dom attributes and values
19087
- attr: function attr($element, namespace, obj) {
19088
  var i;
19089
  var attribute;
19090
  var attributes;
@@ -19097,9 +19099,9 @@ webpackJsonp([3],[
19097
  }
19098
  }
19099
 
19100
- if ('undefined' === typeof $element || 'undefined' === typeof $element[0]) return obj;
19101
 
19102
- attributes = $element[0].attributes;
19103
  for (i = attributes.length; i--;) {
19104
  attribute = attributes[i];
19105
 
@@ -19111,12 +19113,12 @@ webpackJsonp([3],[
19111
  return obj;
19112
  },
19113
 
19114
- checkAttr: function checkAttr($element, namespace, _checkAttr) {
19115
- return $element.is('[' + namespace + _checkAttr + ']');
19116
  },
19117
 
19118
- setAttr: function setAttr($element, namespace, attr, value) {
19119
- $element[0].setAttribute(this.dasherize(namespace + attr), String(value));
19120
  },
19121
 
19122
  generateID: function generateID() {
@@ -19203,7 +19205,7 @@ webpackJsonp([3],[
19203
  return !/^\s*false\s*$/i.test(string);
19204
  },
19205
  object: function object(string) {
19206
- return Utils__Utils.deserializeValue(string);
19207
  },
19208
  regexp: function regexp(_regexp) {
19209
  var flags = '';
@@ -19275,8 +19277,6 @@ webpackJsonp([3],[
19275
  _SubmitSelector: 'input[type="submit"], button:submit'
19276
  };
19277
 
19278
- var Utils__default = Utils__Utils;
19279
-
19280
  // All these options could be overriden and specified directly in DOM using
19281
  // `data-parsley-` default DOM-API
19282
  // eg: `inputs` can be set in DOM using `data-parsley-inputs="input, textarea"`
@@ -19343,7 +19343,7 @@ webpackJsonp([3],[
19343
  };
19344
 
19345
  var Base = function Base() {
19346
- this.__id__ = Utils__default.generateID();
19347
  };
19348
 
19349
  Base.prototype = {
@@ -19361,14 +19361,14 @@ webpackJsonp([3],[
19361
  },
19362
 
19363
  actualizeOptions: function actualizeOptions() {
19364
- Utils__default.attr(this.$element, this.options.namespace, this.domOptions);
19365
  if (this.parent && this.parent.actualizeOptions) this.parent.actualizeOptions();
19366
  return this;
19367
  },
19368
 
19369
  _resetOptions: function _resetOptions(initOptions) {
19370
- this.domOptions = Utils__default.objectCreate(this.parent.options);
19371
- this.options = Utils__default.objectCreate(this.domOptions);
19372
  // Shallow copy of ownProperties of initOptions:
19373
  for (var i in initOptions) {
19374
  if (initOptions.hasOwnProperty(i)) this.options[i] = initOptions[i];
@@ -19434,19 +19434,19 @@ webpackJsonp([3],[
19434
  },
19435
 
19436
  asyncIsValid: function asyncIsValid(group, force) {
19437
- Utils__default.warnOnce("asyncIsValid is deprecated; please use whenValid instead");
19438
  return this.whenValid({ group: group, force: force });
19439
  },
19440
 
19441
  _findRelated: function _findRelated() {
19442
- return this.options.multiple ? this.parent.$element.find('[' + this.options.namespace + 'multiple="' + this.options.multiple + '"]') : this.$element;
19443
  }
19444
  };
19445
 
19446
  var convertArrayRequirement = function convertArrayRequirement(string, length) {
19447
  var m = string.match(/^\s*\[(.*)\]\s*$/);
19448
  if (!m) throw 'Requirement is not an array: "' + string + '"';
19449
- var values = m[1].split(',').map(Utils__default.trimString);
19450
  if (values.length !== length) throw 'Requirement has ' + values.length + ' values when ' + length + ' are needed';
19451
  return values;
19452
  };
@@ -19457,10 +19457,10 @@ webpackJsonp([3],[
19457
  for (var key in requirementSpec) {
19458
  if (key) {
19459
  var value = extraOptionReader(key);
19460
- if ('string' === typeof value) value = Utils__default.parseRequirement(requirementSpec[key], value);
19461
  extra[key] = value;
19462
  } else {
19463
- main = Utils__default.parseRequirement(requirementSpec[key], string);
19464
  }
19465
  }
19466
  return [main, extra];
@@ -19483,13 +19483,13 @@ webpackJsonp([3],[
19483
  return this.fn(value, requirementFirstArg);
19484
  }
19485
 
19486
- if ($.isArray(value)) {
19487
  if (!this.validateMultiple) throw 'Validator `' + this.name + '` does not handle multiple values';
19488
  return this.validateMultiple.apply(this, arguments);
19489
  } else {
19490
  var instance = arguments[arguments.length - 1];
19491
  if (this.validateDate && instance._isDateInput()) {
19492
- arguments[0] = Utils__default.parse.date(arguments[0]);
19493
  if (arguments[0] === null) return false;
19494
  return this.validateDate.apply(this, arguments);
19495
  }
@@ -19511,17 +19511,17 @@ webpackJsonp([3],[
19511
  if ('string' !== typeof requirements) {
19512
  // Assume requirement already parsed
19513
  // but make sure we return an array
19514
- return $.isArray(requirements) ? requirements : [requirements];
19515
  }
19516
  var type = this.requirementType;
19517
- if ($.isArray(type)) {
19518
  var values = convertArrayRequirement(requirements, type.length);
19519
- for (var i = 0; i < values.length; i++) values[i] = Utils__default.parseRequirement(type[i], values[i]);
19520
  return values;
19521
  } else if ($.isPlainObject(type)) {
19522
  return convertExtraOptionRequirement(type, requirements, extraOptionReader);
19523
  } else {
19524
- return [Utils__default.parseRequirement(type, requirements)];
19525
  }
19526
  },
19527
  // Defaults:
@@ -19554,7 +19554,7 @@ webpackJsonp([3],[
19554
 
19555
  date: {
19556
  test: function test(value) {
19557
- return Utils__default.parse.date(value) !== null;
19558
  }
19559
  },
19560
 
@@ -19602,7 +19602,7 @@ webpackJsonp([3],[
19602
 
19603
  // parseArguments('number', ['1', '2']) => [1, 2]
19604
  var ValidatorRegistry__parseArguments = function ValidatorRegistry__parseArguments(type, args) {
19605
- return args.map(Utils__default.parse[type]);
19606
  };
19607
  // operatorToValidator returns a validating function for an operator function, applied to the given type
19608
  var ValidatorRegistry__operatorToValidator = function ValidatorRegistry__operatorToValidator(type, operator) {
@@ -19629,7 +19629,7 @@ webpackJsonp([3],[
19629
  init: function init(validators, catalog) {
19630
  this.catalog = catalog;
19631
  // Copy prototype's validators:
19632
- this.validators = $.extend({}, this.validators);
19633
 
19634
  for (var name in validators) this.addValidator(name, validators[name].fn, validators[name].priority);
19635
 
@@ -19685,8 +19685,8 @@ webpackJsonp([3],[
19685
  // Old API was addValidator(name, function, priority)
19686
  //
19687
  addValidator: function addValidator(name, arg1, arg2) {
19688
- if (this.validators[name]) Utils__default.warn('Validator "' + name + '" is already defined.');else if (Defaults.hasOwnProperty(name)) {
19689
- Utils__default.warn('"' + name + '" is a restricted keyword and is not a valid validator name.');
19690
  return;
19691
  }
19692
  return this._setValidator.apply(this, arguments);
@@ -19694,14 +19694,14 @@ webpackJsonp([3],[
19694
 
19695
  updateValidator: function updateValidator(name, arg1, arg2) {
19696
  if (!this.validators[name]) {
19697
- Utils__default.warn('Validator "' + name + '" is not already defined.');
19698
  return this.addValidator.apply(this, arguments);
19699
  }
19700
  return this._setValidator.apply(this, arguments);
19701
  },
19702
 
19703
  removeValidator: function removeValidator(name) {
19704
- if (!this.validators[name]) Utils__default.warn('Validator "' + name + '" is not defined.');
19705
 
19706
  delete this.validators[name];
19707
 
@@ -19910,14 +19910,14 @@ webpackJsonp([3],[
19910
  this.$element.on('submit.Parsley', function (evt) {
19911
  _this2.onSubmitValidate(evt);
19912
  });
19913
- this.$element.on('click.Parsley', Utils__default._SubmitSelector, function (evt) {
19914
  _this2.onSubmitButton(evt);
19915
  });
19916
 
19917
  // UI could be disabled
19918
  if (false === this.options.uiEnabled) return;
19919
 
19920
- this.$element.attr('novalidate', '');
19921
  },
19922
 
19923
  focus: function focus() {
@@ -20094,7 +20094,7 @@ webpackJsonp([3],[
20094
  var _ui = {};
20095
 
20096
  // Give field its Parsley id in DOM
20097
- this.$element.attr(this.options.namespace + 'id', this.__id__);
20098
 
20099
  /** Generate important UI elements and store them in this **/
20100
  // $errorClassHandler is the $element that woul have parsley-error and parsley-success classes
@@ -20115,10 +20115,15 @@ webpackJsonp([3],[
20115
  // Determine which element will have `parsley-error` and `parsley-success` classes
20116
  _manageClassHandler: function _manageClassHandler() {
20117
  // An element selector could be passed through DOM with `data-parsley-class-handler=#foo`
20118
- if ('string' === typeof this.options.classHandler && $(this.options.classHandler).length) return $(this.options.classHandler);
 
 
 
 
 
20119
 
20120
  // Class handled could also be determined by function given in Parsley options
20121
- var $handler = this.options.classHandler.call(this, this);
20122
 
20123
  // If this function returned a valid existing DOM element, go for it
20124
  if ('undefined' !== typeof $handler && $handler.length) return $handler;
@@ -20128,7 +20133,7 @@ webpackJsonp([3],[
20128
 
20129
  _inputHolder: function _inputHolder() {
20130
  // if simple element (input, texatrea, select...) it will perfectly host the classes and precede the error container
20131
- if (!this.options.multiple || this.$element.is('select')) return this.$element;
20132
 
20133
  // But if multiple element (radio, checkbox), that would be their parent
20134
  return this.$element.parent();
@@ -20141,7 +20146,7 @@ webpackJsonp([3],[
20141
  if (0 !== this._ui.$errorsWrapper.parent().length) return this._ui.$errorsWrapper.parent();
20142
 
20143
  if ('string' === typeof this.options.errorsContainer) {
20144
- if ($(this.options.errorsContainer).length) return $(this.options.errorsContainer).append(this._ui.$errorsWrapper);else Utils__default.warn('The errors container `' + this.options.errorsContainer + '` does not exist in DOM');
20145
  } else if ('function' === typeof this.options.errorsContainer) $errorsContainer = this.options.errorsContainer.call(this, this);
20146
 
20147
  if ('undefined' !== typeof $errorsContainer && $errorsContainer.length) return $errorsContainer.append(this._ui.$errorsWrapper);
@@ -20157,9 +20162,9 @@ webpackJsonp([3],[
20157
 
20158
  // Remove Parsley events already bound on this field
20159
  $toBind.off('.Parsley');
20160
- if (this._failedOnce) $toBind.on(Utils__default.namespaceEvents(this.options.triggerAfterFailure, 'Parsley'), function () {
20161
  _this3._validateIfNeeded();
20162
- });else if (trigger = Utils__default.namespaceEvents(this.options.trigger, 'Parsley')) {
20163
  $toBind.on(trigger, function (event) {
20164
  _this3._validateIfNeeded(event);
20165
  });
@@ -20225,6 +20230,7 @@ webpackJsonp([3],[
20225
  var Form = function Form(element, domOptions, options) {
20226
  this.__class__ = 'Form';
20227
 
 
20228
  this.$element = $(element);
20229
  this.domOptions = domOptions;
20230
  this.options = options;
@@ -20244,10 +20250,12 @@ webpackJsonp([3],[
20244
  if (true === event.parsley) return;
20245
 
20246
  // If we didn't come here through a submit button, use the first one in the form
20247
- var $submitSource = this._$submitSource || this.$element.find(Utils__default._SubmitSelector).first();
20248
- this._$submitSource = null;
20249
  this.$element.find('.parsley-synthetic-submit-button').prop('disabled', true);
20250
- if ($submitSource.is('[formnovalidate]')) return;
 
 
20251
 
20252
  var promise = this.whenValidate({ event: event });
20253
 
@@ -20259,30 +20267,30 @@ webpackJsonp([3],[
20259
  event.stopImmediatePropagation();
20260
  event.preventDefault();
20261
  if ('pending' === promise.state()) promise.done(function () {
20262
- _this5._submit($submitSource);
20263
  });
20264
  }
20265
  },
20266
 
20267
  onSubmitButton: function onSubmitButton(event) {
20268
- this._$submitSource = $(event.currentTarget);
20269
  },
20270
  // internal
20271
  // _submit submits the form, this time without going through the validations.
20272
  // Care must be taken to "fake" the actual submit button being clicked.
20273
- _submit: function _submit($submitSource) {
20274
  if (false === this._trigger('submit')) return;
20275
  // Add submit button's data
20276
- if ($submitSource) {
20277
  var $synthetic = this.$element.find('.parsley-synthetic-submit-button').prop('disabled', false);
20278
  if (0 === $synthetic.length) $synthetic = $('<input class="parsley-synthetic-submit-button" type="hidden">').appendTo(this.$element);
20279
  $synthetic.attr({
20280
- name: $submitSource.attr('name'),
20281
- value: $submitSource.attr('value')
20282
  });
20283
  }
20284
 
20285
- this.$element.trigger($.extend($.Event('submit'), { parsley: true }));
20286
  },
20287
 
20288
  // Performs validation on fields while triggering events.
@@ -20292,7 +20300,7 @@ webpackJsonp([3],[
20292
  // Consider using `whenValidate` instead.
20293
  validate: function validate(options) {
20294
  if (arguments.length >= 1 && !$.isPlainObject(options)) {
20295
- Utils__default.warnOnce('Calling validate on a parsley form without passing arguments as an object is deprecated.');
20296
 
20297
  var _arguments = _slice.call(arguments);
20298
 
@@ -20306,7 +20314,7 @@ webpackJsonp([3],[
20306
  },
20307
 
20308
  whenValidate: function whenValidate() {
20309
- var _Utils__default$all$done$fail$always,
20310
  _this6 = this;
20311
 
20312
  var _ref7 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
@@ -20317,8 +20325,8 @@ webpackJsonp([3],[
20317
 
20318
  this.submitEvent = event;
20319
  if (event) {
20320
- this.submitEvent = $.extend({}, event, { preventDefault: function preventDefault() {
20321
- Utils__default.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`");
20322
  _this6.validationResult = false;
20323
  } });
20324
  }
@@ -20336,7 +20344,7 @@ webpackJsonp([3],[
20336
  });
20337
  });
20338
 
20339
- return (_Utils__default$all$done$fail$always = Utils__default.all(promises).done(function () {
20340
  _this6._trigger('success');
20341
  }).fail(function () {
20342
  _this6.validationResult = false;
@@ -20344,7 +20352,7 @@ webpackJsonp([3],[
20344
  _this6._trigger('error');
20345
  }).always(function () {
20346
  _this6._trigger('validated');
20347
- })).pipe.apply(_Utils__default$all$done$fail$always, _toConsumableArray(this._pipeAccordingToValidationResult()));
20348
  },
20349
 
20350
  // Iterate over refreshed fields, and stop on first failure.
@@ -20353,7 +20361,7 @@ webpackJsonp([3],[
20353
  // Prefer using `whenValid` instead.
20354
  isValid: function isValid(options) {
20355
  if (arguments.length >= 1 && !$.isPlainObject(options)) {
20356
- Utils__default.warnOnce('Calling isValid on a parsley form without passing arguments as an object is deprecated.');
20357
 
20358
  var _arguments2 = _slice.call(arguments);
20359
 
@@ -20383,7 +20391,7 @@ webpackJsonp([3],[
20383
  return field.whenValid({ group: group, force: force });
20384
  });
20385
  });
20386
- return Utils__default.all(promises);
20387
  },
20388
 
20389
  // Reset UI
@@ -20432,7 +20440,7 @@ webpackJsonp([3],[
20432
  }
20433
  });
20434
 
20435
- $.each(Utils__default.difference(oldFields, _this8.fields), function (_, field) {
20436
  field.reset();
20437
  });
20438
  });
@@ -20468,13 +20476,15 @@ webpackJsonp([3],[
20468
  var Constraint = function Constraint(parsleyField, name, requirements, priority, isDomConstraint) {
20469
  var validatorSpec = window.Parsley._validatorRegistry.validators[name];
20470
  var validator = new Validator(validatorSpec);
 
 
20471
 
20472
- $.extend(this, {
20473
  validator: validator,
20474
  name: name,
20475
  requirements: requirements,
20476
- priority: priority || parsleyField.options[name + 'Priority'] || validator.priority,
20477
- isDomConstraint: true === isDomConstraint
20478
  });
20479
  this._parseRequirements(parsleyField.options);
20480
  };
@@ -20503,6 +20513,7 @@ webpackJsonp([3],[
20503
  var Field = function Field(field, domOptions, options, parsleyFormInstance) {
20504
  this.__class__ = 'Field';
20505
 
 
20506
  this.$element = $(field);
20507
 
20508
  // Set parent if we have one
@@ -20531,7 +20542,7 @@ webpackJsonp([3],[
20531
  // `null` if validation is not finished. Prefer using whenValidate
20532
  validate: function validate(options) {
20533
  if (arguments.length >= 1 && !$.isPlainObject(options)) {
20534
- Utils__default.warnOnce('Calling validate on a parsley field without passing arguments as an object is deprecated.');
20535
  options = { options: options };
20536
  }
20537
  var promise = this.whenValidate(options);
@@ -20595,7 +20606,7 @@ webpackJsonp([3],[
20595
  },
20596
 
20597
  _isInGroup: function _isInGroup(group) {
20598
- if ($.isArray(this.options.group)) return -1 !== $.inArray(group, this.options.group);
20599
  return this.options.group === group;
20600
  },
20601
 
@@ -20605,7 +20616,7 @@ webpackJsonp([3],[
20605
  // See also `whenValid`.
20606
  isValid: function isValid(options) {
20607
  if (arguments.length >= 1 && !$.isPlainObject(options)) {
20608
- Utils__default.warnOnce('Calling isValid on a parsley field without passing arguments as an object is deprecated.');
20609
 
20610
  var _arguments3 = _slice.call(arguments);
20611
 
@@ -20656,13 +20667,13 @@ webpackJsonp([3],[
20656
  $.each(groupedConstraints, function (_, constraints) {
20657
  // Process one group of constraints at a time, we validate the constraints
20658
  // and combine the promises together.
20659
- var promise = Utils__default.all($.map(constraints, function (constraint) {
20660
  return _this11._validateConstraint(value, constraint);
20661
  }));
20662
  promises.push(promise);
20663
  if (promise.state() === 'rejected') return false; // Interrupt processing if a group has already failed
20664
  });
20665
- return Utils__default.all(promises);
20666
  },
20667
 
20668
  // @returns a promise
@@ -20673,7 +20684,7 @@ webpackJsonp([3],[
20673
  // Map false to a failed promise
20674
  if (false === result) result = $.Deferred().reject();
20675
  // Make sure we return a promise and that we record failures
20676
- return Utils__default.all([result]).fail(function (errorMessage) {
20677
  if (!(_this12.validationResult instanceof Array)) _this12.validationResult = [];
20678
  _this12.validationResult.push({
20679
  assert: constraint,
@@ -20782,39 +20793,39 @@ webpackJsonp([3],[
20782
  // Bind specific HTML5 constraints to be HTML5 compliant
20783
  _bindHtml5Constraints: function _bindHtml5Constraints() {
20784
  // html5 required
20785
- if (this.$element.attr('required')) this.addConstraint('required', true, undefined, true);
20786
 
20787
  // html5 pattern
20788
- if ('string' === typeof this.$element.attr('pattern')) this.addConstraint('pattern', this.$element.attr('pattern'), undefined, true);
20789
 
20790
  // range
20791
- if ('undefined' !== typeof this.$element.attr('min') && 'undefined' !== typeof this.$element.attr('max')) this.addConstraint('range', [this.$element.attr('min'), this.$element.attr('max')], undefined, true);
 
 
20792
 
20793
  // HTML5 min
20794
- else if ('undefined' !== typeof this.$element.attr('min')) this.addConstraint('min', this.$element.attr('min'), undefined, true);
20795
 
20796
  // HTML5 max
20797
- else if ('undefined' !== typeof this.$element.attr('max')) this.addConstraint('max', this.$element.attr('max'), undefined, true);
20798
 
20799
  // length
20800
- if ('undefined' !== typeof this.$element.attr('minlength') && 'undefined' !== typeof this.$element.attr('maxlength')) this.addConstraint('length', [this.$element.attr('minlength'), this.$element.attr('maxlength')], undefined, true);
20801
 
20802
  // HTML5 minlength
20803
- else if ('undefined' !== typeof this.$element.attr('minlength')) this.addConstraint('minlength', this.$element.attr('minlength'), undefined, true);
20804
 
20805
  // HTML5 maxlength
20806
- else if ('undefined' !== typeof this.$element.attr('maxlength')) this.addConstraint('maxlength', this.$element.attr('maxlength'), undefined, true);
20807
 
20808
  // html5 types
20809
- var type = this.$element.attr('type');
20810
-
20811
- if ('undefined' === typeof type) return this;
20812
 
20813
  // Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise
20814
  if ('number' === type) {
20815
  return this.addConstraint('type', ['number', {
20816
- step: this.$element.attr('step') || '1',
20817
- base: this.$element.attr('min') || this.$element.attr('value')
20818
  }], undefined, true);
20819
  // Regular other HTML5 supported types
20820
  } else if (/^(email|url|range|date)$/i.test(type)) {
@@ -20842,11 +20853,11 @@ webpackJsonp([3],[
20842
  // Use `data-parsley-whitespace="squish"` to auto squish input value
20843
  // Use `data-parsley-whitespace="trim"` to auto trim input value
20844
  _handleWhitespace: function _handleWhitespace(value) {
20845
- if (true === this.options.trimValue) Utils__default.warnOnce('data-parsley-trim-value="true" is deprecated, please use data-parsley-whitespace="trim"');
20846
 
20847
  if ('squish' === this.options.whitespace) value = value.replace(/\s{2,}/g, ' ');
20848
 
20849
- if ('trim' === this.options.whitespace || 'squish' === this.options.whitespace || true === this.options.trimValue) value = Utils__default.trimString(value);
20850
 
20851
  return value;
20852
  },
@@ -20902,7 +20913,7 @@ webpackJsonp([3],[
20902
  this.constraints = [];
20903
 
20904
  // Select multiple special treatment
20905
- if (this.$element.is('select')) {
20906
  this.actualizeOptions()._bindConstraints();
20907
 
20908
  return this;
@@ -20931,21 +20942,23 @@ webpackJsonp([3],[
20931
  if ('function' === typeof this.options.value) return this.options.value(this);else if ('undefined' !== typeof this.options.value) return this.options.value;
20932
 
20933
  // Radio input case
20934
- if (this.$element.is('input[type=radio]')) return this._findRelated().filter(':checked').val() || '';
 
20935
 
20936
- // checkbox input case
20937
- if (this.$element.is('input[type=checkbox]')) {
20938
- var values = [];
20939
 
20940
- this._findRelated().filter(':checked').each(function () {
20941
- values.push($(this).val());
20942
- });
20943
 
20944
- return values;
 
20945
  }
20946
 
20947
  // Select multiple case
20948
- if (this.$element.is('select') && null === this.$element.val()) return [];
20949
 
20950
  // Default case that should never happen
20951
  return this.$element.val();
@@ -20959,6 +20972,7 @@ webpackJsonp([3],[
20959
  };
20960
 
20961
  var Factory = function Factory(element, options, parsleyFormInstance) {
 
20962
  this.$element = $(element);
20963
 
20964
  // If the element has already been bound, returns its saved Parsley instance
@@ -20972,7 +20986,7 @@ webpackJsonp([3],[
20972
  }
20973
 
20974
  if ('object' === typeof options) {
20975
- $.extend(savedparsleyFormInstance.options, options);
20976
  }
20977
 
20978
  return savedparsleyFormInstance;
@@ -20990,21 +21004,21 @@ webpackJsonp([3],[
20990
  Factory.prototype = {
20991
  init: function init(options) {
20992
  this.__class__ = 'Parsley';
20993
- this.__version__ = '2.7.0';
20994
- this.__id__ = Utils__default.generateID();
20995
 
20996
  // Pre-compute options
20997
  this._resetOptions(options);
20998
 
20999
  // A Form instance is obviously a `<form>` element but also every node that is not an input and has the `data-parsley-validate` attribute
21000
- if (this.$element.is('form') || Utils__default.checkAttr(this.$element, this.options.namespace, 'validate') && !this.$element.is(this.options.inputs)) return this.bind('parsleyForm');
21001
 
21002
  // Every other element is bound as a `Field` or `FieldMultiple`
21003
  return this.isMultiple() ? this.handleMultiple() : this.bind('parsleyField');
21004
  },
21005
 
21006
  isMultiple: function isMultiple() {
21007
- return this.$element.is('input[type=radio], input[type=checkbox]') || this.$element.is('select') && 'undefined' !== typeof this.$element.attr('multiple');
21008
  },
21009
 
21010
  // Multiples fields are a real nightmare :(
@@ -21017,17 +21031,16 @@ webpackJsonp([3],[
21017
  var parsleyMultipleInstance;
21018
 
21019
  // Handle multiple name
21020
- if (this.options.multiple) ; // We already have our 'multiple' identifier
21021
- else if ('undefined' !== typeof this.$element.attr('name') && this.$element.attr('name').length) this.options.multiple = name = this.$element.attr('name');else if ('undefined' !== typeof this.$element.attr('id') && this.$element.attr('id').length) this.options.multiple = this.$element.attr('id');
21022
 
21023
  // Special select multiple input
21024
- if (this.$element.is('select') && 'undefined' !== typeof this.$element.attr('multiple')) {
21025
  this.options.multiple = this.options.multiple || this.__id__;
21026
  return this.bind('parsleyFieldMultiple');
21027
 
21028
  // Else for radio / checkboxes, we need a `name` or `data-parsley-multiple` to properly bind it
21029
  } else if (!this.options.multiple) {
21030
- Utils__default.warn('To be bound by Parsley, a radio, a checkbox and a multiple select input must have either a name or a multiple option.', this.$element);
21031
  return this;
21032
  }
21033
 
@@ -21035,9 +21048,9 @@ webpackJsonp([3],[
21035
  this.options.multiple = this.options.multiple.replace(/(:|\.|\[|\]|\{|\}|\$)/g, '');
21036
 
21037
  // Add proper `data-parsley-multiple` to siblings if we have a valid multiple name
21038
- if ('undefined' !== typeof name) {
21039
  $('input[name="' + name + '"]').each(function (i, input) {
21040
- if ($(input).is('input[type=radio], input[type=checkbox]')) $(input).attr(_this13.options.namespace + 'multiple', _this13.options.multiple);
21041
  });
21042
  }
21043
 
@@ -21068,19 +21081,19 @@ webpackJsonp([3],[
21068
 
21069
  switch (type) {
21070
  case 'parsleyForm':
21071
- parsleyInstance = $.extend(new Form(this.$element, this.domOptions, this.options), new Base(), window.ParsleyExtend)._bindFields();
21072
  break;
21073
  case 'parsleyField':
21074
- parsleyInstance = $.extend(new parsley_field(this.$element, this.domOptions, this.options, this.parent), new Base(), window.ParsleyExtend);
21075
  break;
21076
  case 'parsleyFieldMultiple':
21077
- parsleyInstance = $.extend(new parsley_field(this.$element, this.domOptions, this.options, this.parent), new Multiple(), new Base(), window.ParsleyExtend)._init();
21078
  break;
21079
  default:
21080
  throw new Error(type + 'is not a supported Parsley type');
21081
  }
21082
 
21083
- if (this.options.multiple) Utils__default.setAttr(this.$element, this.options.namespace, 'multiple', this.options.multiple);
21084
 
21085
  if ('undefined' !== typeof doNotStore) {
21086
  this.$element.data('FieldMultiple', parsleyInstance);
@@ -21104,23 +21117,24 @@ webpackJsonp([3],[
21104
  throw "The loaded version of jQuery is too old. Please upgrade to 1.8.x or better.";
21105
  }
21106
  if (!vernums.forEach) {
21107
- Utils__default.warn('Parsley requires ES5 to run properly. Please include https://github.com/es-shims/es5-shim');
21108
  }
21109
  // Inherit `on`, `off` & `trigger` to Parsley:
21110
- var Parsley = $.extend(new Base(), {
 
21111
  $element: $(document),
21112
  actualizeOptions: null,
21113
  _resetOptions: null,
21114
  Factory: Factory,
21115
- version: '2.7.0'
21116
  });
21117
 
21118
  // Supplement Field and Form with Base
21119
  // This way, the constructors will have access to those methods
21120
- $.extend(parsley_field.prototype, UI.Field, Base.prototype);
21121
- $.extend(Form.prototype, UI.Form, Base.prototype);
21122
  // Inherit actualizeOptions and _resetOptions:
21123
- $.extend(Factory.prototype, Base.prototype);
21124
 
21125
  // ### jQuery API
21126
  // `$('.elem').parsley(options)` or `$('.elem').psly(options)`
@@ -21137,12 +21151,12 @@ webpackJsonp([3],[
21137
 
21138
  // Return undefined if applied to non existing DOM element
21139
  if (!$(this).length) {
21140
- Utils__default.warn('You must bind Parsley on an existing element.');
21141
 
21142
  return;
21143
  }
21144
 
21145
- return new Factory(this, options);
21146
  };
21147
 
21148
  // ### Field and Form extension
@@ -21151,18 +21165,18 @@ webpackJsonp([3],[
21151
 
21152
  // ### Parsley config
21153
  // Inherit from ParsleyDefault, and copy over any existing values
21154
- Parsley.options = $.extend(Utils__default.objectCreate(Defaults), window.ParsleyConfig);
21155
  window.ParsleyConfig = Parsley.options; // Old way of accessing global options
21156
 
21157
  // ### Globals
21158
  window.Parsley = window.psly = Parsley;
21159
- Parsley.Utils = Utils__default;
21160
  window.ParsleyUtils = {};
21161
- $.each(Utils__default, function (key, value) {
21162
  if ('function' === typeof value) {
21163
  window.ParsleyUtils[key] = function () {
21164
- Utils__default.warnOnce('Accessing `window.ParsleyUtils` is deprecated. Use `window.Parsley.Utils` instead.');
21165
- return Utils__default[key].apply(Utils__default, arguments);
21166
  };
21167
  }
21168
  });
@@ -21171,11 +21185,13 @@ webpackJsonp([3],[
21171
  var registry = window.Parsley._validatorRegistry = new ValidatorRegistry(window.ParsleyConfig.validators, window.ParsleyConfig.i18n);
21172
  window.ParsleyValidator = {};
21173
  $.each('setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator'.split(' '), function (i, method) {
21174
- window.Parsley[method] = $.proxy(registry, method);
 
 
21175
  window.ParsleyValidator[method] = function () {
21176
  var _window$Parsley;
21177
 
21178
- Utils__default.warnOnce('Accessing the method \'' + method + '\' through Validator is deprecated. Simply call \'window.Parsley.' + method + '(...)\'');
21179
  return (_window$Parsley = window.Parsley)[method].apply(_window$Parsley, arguments);
21180
  };
21181
  });
@@ -21186,18 +21202,18 @@ webpackJsonp([3],[
21186
  window.ParsleyUI = {
21187
  removeError: function removeError(instance, name, doNotUpdateClass) {
21188
  var updateClass = true !== doNotUpdateClass;
21189
- Utils__default.warnOnce('Accessing UI is deprecated. Call \'removeError\' on the instance directly. Please comment in issue 1073 as to your need to call this method.');
21190
  return instance.removeError(name, { updateClass: updateClass });
21191
  },
21192
  getErrorsMessages: function getErrorsMessages(instance) {
21193
- Utils__default.warnOnce('Accessing UI is deprecated. Call \'getErrorsMessages\' on the instance directly.');
21194
  return instance.getErrorsMessages();
21195
  }
21196
  };
21197
  $.each('addError updateError'.split(' '), function (i, method) {
21198
  window.ParsleyUI[method] = function (instance, name, message, assert, doNotUpdateClass) {
21199
  var updateClass = true !== doNotUpdateClass;
21200
- Utils__default.warnOnce('Accessing UI is deprecated. Call \'' + method + '\' on the instance directly. Please comment in issue 1073 as to your need to call this method.');
21201
  return instance[method](name, { message: message, assert: assert, updateClass: updateClass });
21202
  };
21203
  });
@@ -21213,7 +21229,7 @@ webpackJsonp([3],[
21213
 
21214
  var o = $({});
21215
  var deprecated = function deprecated() {
21216
- Utils__default.warnOnce("Parsley's pubsub module is deprecated; use the 'on' and 'off' methods on parsley instances or window.Parsley");
21217
  };
21218
 
21219
  // Returns an event handler that calls `fn` with the arguments it expects
@@ -21353,7 +21369,7 @@ webpackJsonp([3],[
21353
  if (url.indexOf('{value}') > -1) {
21354
  url = url.replace('{value}', encodeURIComponent(value));
21355
  } else {
21356
- data[instance.$element.attr('name') || instance.$element.attr('id')] = value;
21357
  }
21358
 
21359
  // Merge options passed in from the function with the ones in the attribute
@@ -21394,7 +21410,7 @@ webpackJsonp([3],[
21394
  Parsley._remoteCache = {};
21395
  });
21396
 
21397
- window.ParsleyExtend.addAsyncValidator = function () {
21398
  Utils.warnOnce('Accessing the method `addAsyncValidator` through an instance is deprecated. Simply call `Parsley.addAsyncValidator(...)`');
21399
  return Parsley.addAsyncValidator.apply(Parsley, arguments);
21400
  };
@@ -21443,7 +21459,7 @@ webpackJsonp([3],[
21443
 
21444
  // Slightly odd way construct our object. This way methods are force bound.
21445
  // Used to test for duplicate library.
21446
- $.extend(this, {
21447
 
21448
  // For browsers that do not support isTrusted, assumes event is native.
21449
  isNativeEvent: function isNativeEvent(evt) {
19057
 
19058
  /* WEBPACK VAR INJECTION */(function(global) {/*!
19059
  * Parsley.js
19060
+ * Version 2.7.2 - built Tue, May 9th 2017, 11:21 am
19061
  * http://parsleyjs.org
19062
  * Guillaume Potier - <guillaume@wisembly.com>
19063
  * Marc-Andre Lafortune - <petroselinum@marc-andre.ca>
19071
 
19072
  var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })();
19073
 
19074
+ var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
19075
+
19076
  function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }
19077
 
19078
  (function (global, factory) {
19083
  var globalID = 1;
19084
  var pastWarnings = {};
19085
 
19086
+ var Utils = {
19087
  // Parsley DOM-API
19088
  // returns object from dom attributes and values
19089
+ attr: function attr(element, namespace, obj) {
19090
  var i;
19091
  var attribute;
19092
  var attributes;
19099
  }
19100
  }
19101
 
19102
+ if (!element) return obj;
19103
 
19104
+ attributes = element.attributes;
19105
  for (i = attributes.length; i--;) {
19106
  attribute = attributes[i];
19107
 
19113
  return obj;
19114
  },
19115
 
19116
+ checkAttr: function checkAttr(element, namespace, _checkAttr) {
19117
+ return element.hasAttribute(namespace + _checkAttr);
19118
  },
19119
 
19120
+ setAttr: function setAttr(element, namespace, attr, value) {
19121
+ element.setAttribute(this.dasherize(namespace + attr), String(value));
19122
  },
19123
 
19124
  generateID: function generateID() {
19205
  return !/^\s*false\s*$/i.test(string);
19206
  },
19207
  object: function object(string) {
19208
+ return Utils.deserializeValue(string);
19209
  },
19210
  regexp: function regexp(_regexp) {
19211
  var flags = '';
19277
  _SubmitSelector: 'input[type="submit"], button:submit'
19278
  };
19279
 
 
 
19280
  // All these options could be overriden and specified directly in DOM using
19281
  // `data-parsley-` default DOM-API
19282
  // eg: `inputs` can be set in DOM using `data-parsley-inputs="input, textarea"`
19343
  };
19344
 
19345
  var Base = function Base() {
19346
+ this.__id__ = Utils.generateID();
19347
  };
19348
 
19349
  Base.prototype = {
19361
  },
19362
 
19363
  actualizeOptions: function actualizeOptions() {
19364
+ Utils.attr(this.element, this.options.namespace, this.domOptions);
19365
  if (this.parent && this.parent.actualizeOptions) this.parent.actualizeOptions();
19366
  return this;
19367
  },
19368
 
19369
  _resetOptions: function _resetOptions(initOptions) {
19370
+ this.domOptions = Utils.objectCreate(this.parent.options);
19371
+ this.options = Utils.objectCreate(this.domOptions);
19372
  // Shallow copy of ownProperties of initOptions:
19373
  for (var i in initOptions) {
19374
  if (initOptions.hasOwnProperty(i)) this.options[i] = initOptions[i];
19434
  },
19435
 
19436
  asyncIsValid: function asyncIsValid(group, force) {
19437
+ Utils.warnOnce("asyncIsValid is deprecated; please use whenValid instead");
19438
  return this.whenValid({ group: group, force: force });
19439
  },
19440
 
19441
  _findRelated: function _findRelated() {
19442
+ return this.options.multiple ? $(this.parent.element.querySelectorAll('[' + this.options.namespace + 'multiple="' + this.options.multiple + '"]')) : this.$element;
19443
  }
19444
  };
19445
 
19446
  var convertArrayRequirement = function convertArrayRequirement(string, length) {
19447
  var m = string.match(/^\s*\[(.*)\]\s*$/);
19448
  if (!m) throw 'Requirement is not an array: "' + string + '"';
19449
+ var values = m[1].split(',').map(Utils.trimString);
19450
  if (values.length !== length) throw 'Requirement has ' + values.length + ' values when ' + length + ' are needed';
19451
  return values;
19452
  };
19457
  for (var key in requirementSpec) {
19458
  if (key) {
19459
  var value = extraOptionReader(key);
19460
+ if ('string' === typeof value) value = Utils.parseRequirement(requirementSpec[key], value);
19461
  extra[key] = value;
19462
  } else {
19463
+ main = Utils.parseRequirement(requirementSpec[key], string);
19464
  }
19465
  }
19466
  return [main, extra];
19483
  return this.fn(value, requirementFirstArg);
19484
  }
19485
 
19486
+ if (Array.isArray(value)) {
19487
  if (!this.validateMultiple) throw 'Validator `' + this.name + '` does not handle multiple values';
19488
  return this.validateMultiple.apply(this, arguments);
19489
  } else {
19490
  var instance = arguments[arguments.length - 1];
19491
  if (this.validateDate && instance._isDateInput()) {
19492
+ arguments[0] = Utils.parse.date(arguments[0]);
19493
  if (arguments[0] === null) return false;
19494
  return this.validateDate.apply(this, arguments);
19495
  }
19511
  if ('string' !== typeof requirements) {
19512
  // Assume requirement already parsed
19513
  // but make sure we return an array
19514
+ return Array.isArray(requirements) ? requirements : [requirements];
19515
  }
19516
  var type = this.requirementType;
19517
+ if (Array.isArray(type)) {
19518
  var values = convertArrayRequirement(requirements, type.length);
19519
+ for (var i = 0; i < values.length; i++) values[i] = Utils.parseRequirement(type[i], values[i]);
19520
  return values;
19521
  } else if ($.isPlainObject(type)) {
19522
  return convertExtraOptionRequirement(type, requirements, extraOptionReader);
19523
  } else {
19524
+ return [Utils.parseRequirement(type, requirements)];
19525
  }
19526
  },
19527
  // Defaults:
19554
 
19555
  date: {
19556
  test: function test(value) {
19557
+ return Utils.parse.date(value) !== null;
19558
  }
19559
  },
19560
 
19602
 
19603
  // parseArguments('number', ['1', '2']) => [1, 2]
19604
  var ValidatorRegistry__parseArguments = function ValidatorRegistry__parseArguments(type, args) {
19605
+ return args.map(Utils.parse[type]);
19606
  };
19607
  // operatorToValidator returns a validating function for an operator function, applied to the given type
19608
  var ValidatorRegistry__operatorToValidator = function ValidatorRegistry__operatorToValidator(type, operator) {
19629
  init: function init(validators, catalog) {
19630
  this.catalog = catalog;
19631
  // Copy prototype's validators:
19632
+ this.validators = _extends({}, this.validators);
19633
 
19634
  for (var name in validators) this.addValidator(name, validators[name].fn, validators[name].priority);
19635
 
19685
  // Old API was addValidator(name, function, priority)
19686
  //
19687
  addValidator: function addValidator(name, arg1, arg2) {
19688
+ if (this.validators[name]) Utils.warn('Validator "' + name + '" is already defined.');else if (Defaults.hasOwnProperty(name)) {
19689
+ Utils.warn('"' + name + '" is a restricted keyword and is not a valid validator name.');
19690
  return;
19691
  }
19692
  return this._setValidator.apply(this, arguments);
19694
 
19695
  updateValidator: function updateValidator(name, arg1, arg2) {
19696
  if (!this.validators[name]) {
19697
+ Utils.warn('Validator "' + name + '" is not already defined.');
19698
  return this.addValidator.apply(this, arguments);
19699
  }
19700
  return this._setValidator.apply(this, arguments);
19701
  },
19702
 
19703
  removeValidator: function removeValidator(name) {
19704
+ if (!this.validators[name]) Utils.warn('Validator "' + name + '" is not defined.');
19705
 
19706
  delete this.validators[name];
19707
 
19910
  this.$element.on('submit.Parsley', function (evt) {
19911
  _this2.onSubmitValidate(evt);
19912
  });
19913
+ this.$element.on('click.Parsley', Utils._SubmitSelector, function (evt) {
19914
  _this2.onSubmitButton(evt);
19915
  });
19916
 
19917
  // UI could be disabled
19918
  if (false === this.options.uiEnabled) return;
19919
 
19920
+ this.element.setAttribute('novalidate', '');
19921
  },
19922
 
19923
  focus: function focus() {
20094
  var _ui = {};
20095
 
20096
  // Give field its Parsley id in DOM
20097
+ this.element.setAttribute(this.options.namespace + 'id', this.__id__);
20098
 
20099
  /** Generate important UI elements and store them in this **/
20100
  // $errorClassHandler is the $element that woul have parsley-error and parsley-success classes
20115
  // Determine which element will have `parsley-error` and `parsley-success` classes
20116
  _manageClassHandler: function _manageClassHandler() {
20117
  // An element selector could be passed through DOM with `data-parsley-class-handler=#foo`
20118
+ if ('string' === typeof this.options.classHandler) {
20119
+ if ($(this.options.classHandler).length === 0) ParsleyUtils.warn('No elements found that match the selector `' + this.options.classHandler + '` set in options.classHandler or data-parsley-class-handler');
20120
+
20121
+ //return element or empty set
20122
+ return $(this.options.classHandler);
20123
+ }
20124
 
20125
  // Class handled could also be determined by function given in Parsley options
20126
+ if ('function' === typeof this.options.classHandler) var $handler = this.options.classHandler.call(this, this);
20127
 
20128
  // If this function returned a valid existing DOM element, go for it
20129
  if ('undefined' !== typeof $handler && $handler.length) return $handler;
20133
 
20134
  _inputHolder: function _inputHolder() {
20135
  // if simple element (input, texatrea, select...) it will perfectly host the classes and precede the error container
20136
+ if (!this.options.multiple || this.element.nodeName === 'SELECT') return this.$element;
20137
 
20138
  // But if multiple element (radio, checkbox), that would be their parent
20139
  return this.$element.parent();
20146
  if (0 !== this._ui.$errorsWrapper.parent().length) return this._ui.$errorsWrapper.parent();
20147
 
20148
  if ('string' === typeof this.options.errorsContainer) {
20149
+ if ($(this.options.errorsContainer).length) return $(this.options.errorsContainer).append(this._ui.$errorsWrapper);else Utils.warn('The errors container `' + this.options.errorsContainer + '` does not exist in DOM');
20150
  } else if ('function' === typeof this.options.errorsContainer) $errorsContainer = this.options.errorsContainer.call(this, this);
20151
 
20152
  if ('undefined' !== typeof $errorsContainer && $errorsContainer.length) return $errorsContainer.append(this._ui.$errorsWrapper);
20162
 
20163
  // Remove Parsley events already bound on this field
20164
  $toBind.off('.Parsley');
20165
+ if (this._failedOnce) $toBind.on(Utils.namespaceEvents(this.options.triggerAfterFailure, 'Parsley'), function () {
20166
  _this3._validateIfNeeded();
20167
+ });else if (trigger = Utils.namespaceEvents(this.options.trigger, 'Parsley')) {
20168
  $toBind.on(trigger, function (event) {
20169
  _this3._validateIfNeeded(event);
20170
  });
20230
  var Form = function Form(element, domOptions, options) {
20231
  this.__class__ = 'Form';
20232
 
20233
+ this.element = element;
20234
  this.$element = $(element);
20235
  this.domOptions = domOptions;
20236
  this.options = options;
20250
  if (true === event.parsley) return;
20251
 
20252
  // If we didn't come here through a submit button, use the first one in the form
20253
+ var submitSource = this._submitSource || this.$element.find(Utils._SubmitSelector)[0];
20254
+ this._submitSource = null;
20255
  this.$element.find('.parsley-synthetic-submit-button').prop('disabled', true);
20256
+ if (submitSource && null !== submitSource.getAttribute('formnovalidate')) return;
20257
+
20258
+ window.Parsley._remoteCache = {};
20259
 
20260
  var promise = this.whenValidate({ event: event });
20261
 
20267
  event.stopImmediatePropagation();
20268
  event.preventDefault();
20269
  if ('pending' === promise.state()) promise.done(function () {
20270
+ _this5._submit(submitSource);
20271
  });
20272
  }
20273
  },
20274
 
20275
  onSubmitButton: function onSubmitButton(event) {
20276
+ this._submitSource = event.currentTarget;
20277
  },
20278
  // internal
20279
  // _submit submits the form, this time without going through the validations.
20280
  // Care must be taken to "fake" the actual submit button being clicked.
20281
+ _submit: function _submit(submitSource) {
20282
  if (false === this._trigger('submit')) return;
20283
  // Add submit button's data
20284
+ if (submitSource) {
20285
  var $synthetic = this.$element.find('.parsley-synthetic-submit-button').prop('disabled', false);
20286
  if (0 === $synthetic.length) $synthetic = $('<input class="parsley-synthetic-submit-button" type="hidden">').appendTo(this.$element);
20287
  $synthetic.attr({
20288
+ name: submitSource.getAttribute('name'),
20289
+ value: submitSource.getAttribute('value')
20290
  });
20291
  }
20292
 
20293
+ this.$element.trigger(_extends($.Event('submit'), { parsley: true }));
20294
  },
20295
 
20296
  // Performs validation on fields while triggering events.
20300
  // Consider using `whenValidate` instead.
20301
  validate: function validate(options) {
20302
  if (arguments.length >= 1 && !$.isPlainObject(options)) {
20303
+ Utils.warnOnce('Calling validate on a parsley form without passing arguments as an object is deprecated.');
20304
 
20305
  var _arguments = _slice.call(arguments);
20306
 
20314
  },
20315
 
20316
  whenValidate: function whenValidate() {
20317
+ var _Utils$all$done$fail$always,
20318
  _this6 = this;
20319
 
20320
  var _ref7 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
20325
 
20326
  this.submitEvent = event;
20327
  if (event) {
20328
+ this.submitEvent = _extends({}, event, { preventDefault: function preventDefault() {
20329
+ Utils.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`");
20330
  _this6.validationResult = false;
20331
  } });
20332
  }
20344
  });
20345
  });
20346
 
20347
+ return (_Utils$all$done$fail$always = Utils.all(promises).done(function () {
20348
  _this6._trigger('success');
20349
  }).fail(function () {
20350
  _this6.validationResult = false;
20352
  _this6._trigger('error');
20353
  }).always(function () {
20354
  _this6._trigger('validated');
20355
+ })).pipe.apply(_Utils$all$done$fail$always, _toConsumableArray(this._pipeAccordingToValidationResult()));
20356
  },
20357
 
20358
  // Iterate over refreshed fields, and stop on first failure.
20361
  // Prefer using `whenValid` instead.
20362
  isValid: function isValid(options) {
20363
  if (arguments.length >= 1 && !$.isPlainObject(options)) {
20364
+ Utils.warnOnce('Calling isValid on a parsley form without passing arguments as an object is deprecated.');
20365
 
20366
  var _arguments2 = _slice.call(arguments);
20367
 
20391
  return field.whenValid({ group: group, force: force });
20392
  });
20393
  });
20394
+ return Utils.all(promises);
20395
  },
20396
 
20397
  // Reset UI
20440
  }
20441
  });
20442
 
20443
+ $.each(Utils.difference(oldFields, _this8.fields), function (_, field) {
20444
  field.reset();
20445
  });
20446
  });
20476
  var Constraint = function Constraint(parsleyField, name, requirements, priority, isDomConstraint) {
20477
  var validatorSpec = window.Parsley._validatorRegistry.validators[name];
20478
  var validator = new Validator(validatorSpec);
20479
+ priority = priority || parsleyField.options[name + 'Priority'] || validator.priority;
20480
+ isDomConstraint = true === isDomConstraint;
20481
 
20482
+ _extends(this, {
20483
  validator: validator,
20484
  name: name,
20485
  requirements: requirements,
20486
+ priority: priority,
20487
+ isDomConstraint: isDomConstraint
20488
  });
20489
  this._parseRequirements(parsleyField.options);
20490
  };
20513
  var Field = function Field(field, domOptions, options, parsleyFormInstance) {
20514
  this.__class__ = 'Field';
20515
 
20516
+ this.element = field;
20517
  this.$element = $(field);
20518
 
20519
  // Set parent if we have one
20542
  // `null` if validation is not finished. Prefer using whenValidate
20543
  validate: function validate(options) {
20544
  if (arguments.length >= 1 && !$.isPlainObject(options)) {
20545
+ Utils.warnOnce('Calling validate on a parsley field without passing arguments as an object is deprecated.');
20546
  options = { options: options };
20547
  }
20548
  var promise = this.whenValidate(options);
20606
  },
20607
 
20608
  _isInGroup: function _isInGroup(group) {
20609
+ if (Array.isArray(this.options.group)) return -1 !== $.inArray(group, this.options.group);
20610
  return this.options.group === group;
20611
  },
20612
 
20616
  // See also `whenValid`.
20617
  isValid: function isValid(options) {
20618
  if (arguments.length >= 1 && !$.isPlainObject(options)) {
20619
+ Utils.warnOnce('Calling isValid on a parsley field without passing arguments as an object is deprecated.');
20620
 
20621
  var _arguments3 = _slice.call(arguments);
20622
 
20667
  $.each(groupedConstraints, function (_, constraints) {
20668
  // Process one group of constraints at a time, we validate the constraints
20669
  // and combine the promises together.
20670
+ var promise = Utils.all($.map(constraints, function (constraint) {
20671
  return _this11._validateConstraint(value, constraint);
20672
  }));
20673
  promises.push(promise);
20674
  if (promise.state() === 'rejected') return false; // Interrupt processing if a group has already failed
20675
  });
20676
+ return Utils.all(promises);
20677
  },
20678
 
20679
  // @returns a promise
20684
  // Map false to a failed promise
20685
  if (false === result) result = $.Deferred().reject();
20686
  // Make sure we return a promise and that we record failures
20687
+ return Utils.all([result]).fail(function (errorMessage) {
20688
  if (!(_this12.validationResult instanceof Array)) _this12.validationResult = [];
20689
  _this12.validationResult.push({
20690
  assert: constraint,
20793
  // Bind specific HTML5 constraints to be HTML5 compliant
20794
  _bindHtml5Constraints: function _bindHtml5Constraints() {
20795
  // html5 required
20796
+ if (null !== this.element.getAttribute('required')) this.addConstraint('required', true, undefined, true);
20797
 
20798
  // html5 pattern
20799
+ if (null !== this.element.getAttribute('pattern')) this.addConstraint('pattern', this.element.getAttribute('pattern'), undefined, true);
20800
 
20801
  // range
20802
+ var min = this.element.getAttribute('min');
20803
+ var max = this.element.getAttribute('max');
20804
+ if (null !== min && null !== max) this.addConstraint('range', [min, max], undefined, true);
20805
 
20806
  // HTML5 min
20807
+ else if (null !== min) this.addConstraint('min', min, undefined, true);
20808
 
20809
  // HTML5 max
20810
+ else if (null !== max) this.addConstraint('max', max, undefined, true);
20811
 
20812
  // length
20813
+ if (null !== this.element.getAttribute('minlength') && null !== this.element.getAttribute('maxlength')) this.addConstraint('length', [this.element.getAttribute('minlength'), this.element.getAttribute('maxlength')], undefined, true);
20814
 
20815
  // HTML5 minlength
20816
+ else if (null !== this.element.getAttribute('minlength')) this.addConstraint('minlength', this.element.getAttribute('minlength'), undefined, true);
20817
 
20818
  // HTML5 maxlength
20819
+ else if (null !== this.element.getAttribute('maxlength')) this.addConstraint('maxlength', this.element.getAttribute('maxlength'), undefined, true);
20820
 
20821
  // html5 types
20822
+ var type = this.element.type;
 
 
20823
 
20824
  // Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise
20825
  if ('number' === type) {
20826
  return this.addConstraint('type', ['number', {
20827
+ step: this.element.getAttribute('step') || '1',
20828
+ base: min || this.element.getAttribute('value')
20829
  }], undefined, true);
20830
  // Regular other HTML5 supported types
20831
  } else if (/^(email|url|range|date)$/i.test(type)) {
20853
  // Use `data-parsley-whitespace="squish"` to auto squish input value
20854
  // Use `data-parsley-whitespace="trim"` to auto trim input value
20855
  _handleWhitespace: function _handleWhitespace(value) {
20856
+ if (true === this.options.trimValue) Utils.warnOnce('data-parsley-trim-value="true" is deprecated, please use data-parsley-whitespace="trim"');
20857
 
20858
  if ('squish' === this.options.whitespace) value = value.replace(/\s{2,}/g, ' ');
20859
 
20860
+ if ('trim' === this.options.whitespace || 'squish' === this.options.whitespace || true === this.options.trimValue) value = Utils.trimString(value);
20861
 
20862
  return value;
20863
  },
20913
  this.constraints = [];
20914
 
20915
  // Select multiple special treatment
20916
+ if (this.element.nodeName === 'SELECT') {
20917
  this.actualizeOptions()._bindConstraints();
20918
 
20919
  return this;
20942
  if ('function' === typeof this.options.value) return this.options.value(this);else if ('undefined' !== typeof this.options.value) return this.options.value;
20943
 
20944
  // Radio input case
20945
+ if (this.element.nodeName === 'INPUT') {
20946
+ if (this.element.type === 'radio') return this._findRelated().filter(':checked').val() || '';
20947
 
20948
+ // checkbox input case
20949
+ if (this.element.type === 'checkbox') {
20950
+ var values = [];
20951
 
20952
+ this._findRelated().filter(':checked').each(function () {
20953
+ values.push($(this).val());
20954
+ });
20955
 
20956
+ return values;
20957
+ }
20958
  }
20959
 
20960
  // Select multiple case
20961
+ if (this.element.nodeName === 'SELECT' && null === this.$element.val()) return [];
20962
 
20963
  // Default case that should never happen
20964
  return this.$element.val();
20972
  };
20973
 
20974
  var Factory = function Factory(element, options, parsleyFormInstance) {
20975
+ this.element = element;
20976
  this.$element = $(element);
20977
 
20978
  // If the element has already been bound, returns its saved Parsley instance
20986
  }
20987
 
20988
  if ('object' === typeof options) {
20989
+ _extends(savedparsleyFormInstance.options, options);
20990
  }
20991
 
20992
  return savedparsleyFormInstance;
21004
  Factory.prototype = {
21005
  init: function init(options) {
21006
  this.__class__ = 'Parsley';
21007
+ this.__version__ = '2.7.2';
21008
+ this.__id__ = Utils.generateID();
21009
 
21010
  // Pre-compute options
21011
  this._resetOptions(options);
21012
 
21013
  // A Form instance is obviously a `<form>` element but also every node that is not an input and has the `data-parsley-validate` attribute
21014
+ if (this.element.nodeName === 'FORM' || Utils.checkAttr(this.element, this.options.namespace, 'validate') && !this.$element.is(this.options.inputs)) return this.bind('parsleyForm');
21015
 
21016
  // Every other element is bound as a `Field` or `FieldMultiple`
21017
  return this.isMultiple() ? this.handleMultiple() : this.bind('parsleyField');
21018
  },
21019
 
21020
  isMultiple: function isMultiple() {
21021
+ return this.element.type === 'radio' || this.element.type === 'checkbox' || this.element.nodeName === 'SELECT' && null !== this.element.getAttribute('multiple');
21022
  },
21023
 
21024
  // Multiples fields are a real nightmare :(
21031
  var parsleyMultipleInstance;
21032
 
21033
  // Handle multiple name
21034
+ this.options.multiple = this.options.multiple || (name = this.element.getAttribute('name')) || this.element.getAttribute('id');
 
21035
 
21036
  // Special select multiple input
21037
+ if (this.element.nodeName === 'SELECT' && null !== this.element.getAttribute('multiple')) {
21038
  this.options.multiple = this.options.multiple || this.__id__;
21039
  return this.bind('parsleyFieldMultiple');
21040
 
21041
  // Else for radio / checkboxes, we need a `name` or `data-parsley-multiple` to properly bind it
21042
  } else if (!this.options.multiple) {
21043
+ Utils.warn('To be bound by Parsley, a radio, a checkbox and a multiple select input must have either a name or a multiple option.', this.$element);
21044
  return this;
21045
  }
21046
 
21048
  this.options.multiple = this.options.multiple.replace(/(:|\.|\[|\]|\{|\}|\$)/g, '');
21049
 
21050
  // Add proper `data-parsley-multiple` to siblings if we have a valid multiple name
21051
+ if (name) {
21052
  $('input[name="' + name + '"]').each(function (i, input) {
21053
+ if (input.type === 'radio' || input.type === 'checkbox') input.setAttribute(_this13.options.namespace + 'multiple', _this13.options.multiple);
21054
  });
21055
  }
21056
 
21081
 
21082
  switch (type) {
21083
  case 'parsleyForm':
21084
+ parsleyInstance = $.extend(new Form(this.element, this.domOptions, this.options), new Base(), window.ParsleyExtend)._bindFields();
21085
  break;
21086
  case 'parsleyField':
21087
+ parsleyInstance = $.extend(new parsley_field(this.element, this.domOptions, this.options, this.parent), new Base(), window.ParsleyExtend);
21088
  break;
21089
  case 'parsleyFieldMultiple':
21090
+ parsleyInstance = $.extend(new parsley_field(this.element, this.domOptions, this.options, this.parent), new Multiple(), new Base(), window.ParsleyExtend)._init();
21091
  break;
21092
  default:
21093
  throw new Error(type + 'is not a supported Parsley type');
21094
  }
21095
 
21096
+ if (this.options.multiple) Utils.setAttr(this.element, this.options.namespace, 'multiple', this.options.multiple);
21097
 
21098
  if ('undefined' !== typeof doNotStore) {
21099
  this.$element.data('FieldMultiple', parsleyInstance);
21117
  throw "The loaded version of jQuery is too old. Please upgrade to 1.8.x or better.";
21118
  }
21119
  if (!vernums.forEach) {
21120
+ Utils.warn('Parsley requires ES5 to run properly. Please include https://github.com/es-shims/es5-shim');
21121
  }
21122
  // Inherit `on`, `off` & `trigger` to Parsley:
21123
+ var Parsley = _extends(new Base(), {
21124
+ element: document,
21125
  $element: $(document),
21126
  actualizeOptions: null,
21127
  _resetOptions: null,
21128
  Factory: Factory,
21129
+ version: '2.7.2'
21130
  });
21131
 
21132
  // Supplement Field and Form with Base
21133
  // This way, the constructors will have access to those methods
21134
+ _extends(parsley_field.prototype, UI.Field, Base.prototype);
21135
+ _extends(Form.prototype, UI.Form, Base.prototype);
21136
  // Inherit actualizeOptions and _resetOptions:
21137
+ _extends(Factory.prototype, Base.prototype);
21138
 
21139
  // ### jQuery API
21140
  // `$('.elem').parsley(options)` or `$('.elem').psly(options)`
21151
 
21152
  // Return undefined if applied to non existing DOM element
21153
  if (!$(this).length) {
21154
+ Utils.warn('You must bind Parsley on an existing element.');
21155
 
21156
  return;
21157
  }
21158
 
21159
+ return new Factory(this[0], options);
21160
  };
21161
 
21162
  // ### Field and Form extension
21165
 
21166
  // ### Parsley config
21167
  // Inherit from ParsleyDefault, and copy over any existing values
21168
+ Parsley.options = _extends(Utils.objectCreate(Defaults), window.ParsleyConfig);
21169
  window.ParsleyConfig = Parsley.options; // Old way of accessing global options
21170
 
21171
  // ### Globals
21172
  window.Parsley = window.psly = Parsley;
21173
+ Parsley.Utils = Utils;
21174
  window.ParsleyUtils = {};
21175
+ $.each(Utils, function (key, value) {
21176
  if ('function' === typeof value) {
21177
  window.ParsleyUtils[key] = function () {
21178
+ Utils.warnOnce('Accessing `window.ParsleyUtils` is deprecated. Use `window.Parsley.Utils` instead.');
21179
+ return Utils[key].apply(Utils, arguments);
21180
  };
21181
  }
21182
  });
21185
  var registry = window.Parsley._validatorRegistry = new ValidatorRegistry(window.ParsleyConfig.validators, window.ParsleyConfig.i18n);
21186
  window.ParsleyValidator = {};
21187
  $.each('setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator'.split(' '), function (i, method) {
21188
+ window.Parsley[method] = function () {
21189
+ return registry[method].apply(registry, arguments);
21190
+ };
21191
  window.ParsleyValidator[method] = function () {
21192
  var _window$Parsley;
21193
 
21194
+ Utils.warnOnce('Accessing the method \'' + method + '\' through Validator is deprecated. Simply call \'window.Parsley.' + method + '(...)\'');
21195
  return (_window$Parsley = window.Parsley)[method].apply(_window$Parsley, arguments);
21196
  };
21197
  });
21202
  window.ParsleyUI = {
21203
  removeError: function removeError(instance, name, doNotUpdateClass) {
21204
  var updateClass = true !== doNotUpdateClass;
21205
+ Utils.warnOnce('Accessing UI is deprecated. Call \'removeError\' on the instance directly. Please comment in issue 1073 as to your need to call this method.');
21206
  return instance.removeError(name, { updateClass: updateClass });
21207
  },
21208
  getErrorsMessages: function getErrorsMessages(instance) {
21209
+ Utils.warnOnce('Accessing UI is deprecated. Call \'getErrorsMessages\' on the instance directly.');
21210
  return instance.getErrorsMessages();
21211
  }
21212
  };
21213
  $.each('addError updateError'.split(' '), function (i, method) {
21214
  window.ParsleyUI[method] = function (instance, name, message, assert, doNotUpdateClass) {
21215
  var updateClass = true !== doNotUpdateClass;
21216
+ Utils.warnOnce('Accessing UI is deprecated. Call \'' + method + '\' on the instance directly. Please comment in issue 1073 as to your need to call this method.');
21217
  return instance[method](name, { message: message, assert: assert, updateClass: updateClass });
21218
  };
21219
  });
21229
 
21230
  var o = $({});
21231
  var deprecated = function deprecated() {
21232
+ Utils.warnOnce("Parsley's pubsub module is deprecated; use the 'on' and 'off' methods on parsley instances or window.Parsley");
21233
  };
21234
 
21235
  // Returns an event handler that calls `fn` with the arguments it expects
21369
  if (url.indexOf('{value}') > -1) {
21370
  url = url.replace('{value}', encodeURIComponent(value));
21371
  } else {
21372
+ data[instance.element.getAttribute('name') || instance.element.getAttribute('id')] = value;
21373
  }
21374
 
21375
  // Merge options passed in from the function with the ones in the attribute
21410
  Parsley._remoteCache = {};
21411
  });
21412
 
21413
+ Base.prototype.addAsyncValidator = function () {
21414
  Utils.warnOnce('Accessing the method `addAsyncValidator` through an instance is deprecated. Simply call `Parsley.addAsyncValidator(...)`');
21415
  return Parsley.addAsyncValidator.apply(Parsley, arguments);
21416
  };
21459
 
21460
  // Slightly odd way construct our object. This way methods are force bound.
21461
  // Used to test for duplicate library.
21462
+ _extends(this, {
21463
 
21464
  // For browsers that do not support isTrusted, assumes event is native.
21465
  isNativeEvent: function isNativeEvent(evt) {
assets/js/mp2migrator.js ADDED
@@ -0,0 +1,259 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /******/ (function(modules) { // webpackBootstrap
2
+ /******/ // The module cache
3
+ /******/ var installedModules = {};
4
+
5
+ /******/ // The require function
6
+ /******/ function __webpack_require__(moduleId) {
7
+
8
+ /******/ // Check if module is in cache
9
+ /******/ if(installedModules[moduleId])
10
+ /******/ return installedModules[moduleId].exports;
11
+
12
+ /******/ // Create a new module (and put it into the cache)
13
+ /******/ var module = installedModules[moduleId] = {
14
+ /******/ exports: {},
15
+ /******/ id: moduleId,
16
+ /******/ loaded: false
17
+ /******/ };
18
+
19
+ /******/ // Execute the module function
20
+ /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21
+
22
+ /******/ // Flag the module as loaded
23
+ /******/ module.loaded = true;
24
+
25
+ /******/ // Return the exports of the module
26
+ /******/ return module.exports;
27
+ /******/ }
28
+
29
+
30
+ /******/ // expose the modules object (__webpack_modules__)
31
+ /******/ __webpack_require__.m = modules;
32
+
33
+ /******/ // expose the module cache
34
+ /******/ __webpack_require__.c = installedModules;
35
+
36
+ /******/ // __webpack_public_path__
37
+ /******/ __webpack_require__.p = "";
38
+
39
+ /******/ // Load entry module and return exports
40
+ /******/ return __webpack_require__(0);
41
+ /******/ })
42
+ /************************************************************************/
43
+ /******/ ([
44
+ /* 0 */
45
+ /***/ function(module, exports, __webpack_require__) {
46
+
47
+ module.exports = __webpack_require__(1);
48
+
49
+
50
+ /***/ },
51
+ /* 1 */
52
+ /***/ function(module, exports) {
53
+
54
+ (function ($) {
55
+ 'use strict';
56
+
57
+ var that;
58
+
59
+ var mailpoet_import = {
60
+ fatal_error: '',
61
+ is_logging: false,
62
+
63
+ /**
64
+ * Start the logger
65
+ */
66
+ start_logger: function () {
67
+ that.is_logging = true;
68
+ clearTimeout(that.display_logs_timeout);
69
+ clearTimeout(that.update_progressbar_timeout);
70
+ clearTimeout(that.update_wordpress_info_timeout);
71
+ that.update_display();
72
+ },
73
+
74
+ /**
75
+ * Stop the logger
76
+ */
77
+ stop_logger: function () {
78
+ that.is_logging = false;
79
+ },
80
+
81
+ /**
82
+ * Update the display
83
+ */
84
+ update_display: function () {
85
+ that.display_logs();
86
+ that.update_progressbar();
87
+ },
88
+
89
+ /**
90
+ * Display the logs
91
+ */
92
+ display_logs: function () {
93
+ $.ajax({
94
+ url: objectPlugin.log_file_url,
95
+ cache: false
96
+ }).done(function (result) {
97
+ $('#action_message').html(''); // Clear the action message
98
+ $("#logger").html('');
99
+ result.split("\n").forEach(function (row) {
100
+ if(row.substr(0, 7) === '[ERROR]' || row.substr(0, 9) === '[WARNING]' || row === 'IMPORT STOPPED BY USER') {
101
+ row = '<span class="error_msg">' + row + '</span>'; // Mark the errors in red
102
+ }
103
+ // Test if the import is complete
104
+ else if(row === 'IMPORT COMPLETE') {
105
+ row = '<span class="complete_msg">' + row + '</span>'; // Mark the complete message in green
106
+ $('#action_message').html(MailPoet.I18n.t('import_complete'))
107
+ .removeClass('failure').addClass('success');
108
+ }
109
+ $("#logger").append(row + "<br />\n");
110
+
111
+ });
112
+ $("#logger").append('<span class="error_msg">' + that.fatal_error + '</span>' + "<br />\n");
113
+ }).always(function () {
114
+ if(that.is_logging) {
115
+ that.display_logs_timeout = setTimeout(that.display_logs, 1000);
116
+ }
117
+ });
118
+ },
119
+
120
+ /**
121
+ * Update the progressbar
122
+ */
123
+ update_progressbar: function () {
124
+ $.ajax({
125
+ url: objectPlugin.progress_url,
126
+ cache: false,
127
+ dataType: 'json'
128
+ }).always(function (result) {
129
+ // Move the progress bar
130
+ var progress = Math.round(Number(result.current) / Number(result.total) * 100);
131
+ $('#progressbar').progressbar('option', 'value', progress);
132
+ $('#progresslabel').html(progress + '%');
133
+ if(that.is_logging) {
134
+ that.update_progressbar_timeout = setTimeout(that.update_progressbar, 1000);
135
+ }
136
+ });
137
+ },
138
+
139
+ /**
140
+ * Start the import
141
+ *
142
+ * @returns {Boolean}
143
+ */
144
+ start_import: function () {
145
+ that.fatal_error = '';
146
+ // Start displaying the logs
147
+ that.start_logger();
148
+
149
+ // Disable the import button
150
+ that.import_button_label = $('#import').val();
151
+ $('#import').val(MailPoet.I18n.t('importing')).attr('disabled', 'disabled');
152
+ // Show the stop button
153
+ $('#stop-import').show();
154
+ // Clear the action message
155
+ $('#action_message').html('');
156
+
157
+ // Run the import
158
+ MailPoet.Ajax.post({
159
+ api_version: window.mailpoet_api_version,
160
+ endpoint: 'MP2Migrator',
161
+ action: 'import',
162
+ data: {
163
+ }
164
+ }).always(function () {
165
+ that.stop_logger();
166
+ that.update_display(); // Get the latest information after the import was stopped
167
+ that.reactivate_import_button();
168
+ }).done(function (response) {
169
+ if(response) {
170
+ that.fatal_error = response.data;
171
+ }
172
+ }).fail(function (response) {
173
+ if(response.errors.length > 0) {
174
+ MailPoet.Notice.error(
175
+ response.errors.map(function (error) {
176
+ return error.message;
177
+ }),
178
+ {scroll: true}
179
+ );
180
+ }
181
+ });
182
+ return false;
183
+ },
184
+
185
+ /**
186
+ * Reactivate the import button
187
+ *
188
+ */
189
+ reactivate_import_button: function () {
190
+ $('#import').val(that.import_button_label).removeAttr('disabled');
191
+ $('#stop-import').hide();
192
+ },
193
+
194
+ /**
195
+ * Stop the import
196
+ *
197
+ * @returns {Boolean}
198
+ */
199
+ stop_import: function () {
200
+ $('#stop-import').attr('disabled', 'disabled');
201
+ // Stop the import
202
+ MailPoet.Ajax.post({
203
+ api_version: window.mailpoet_api_version,
204
+ endpoint: 'MP2Migrator',
205
+ action: 'stopImport',
206
+ data: {
207
+ }
208
+ }).always(function () {
209
+ $('#stop-import').removeAttr('disabled'); // Enable the button
210
+ that.reactivate_import_button();
211
+ that.update_display(); // Get the latest information after the import was stopped
212
+ });
213
+ that.stop_logger();
214
+ return false;
215
+ },
216
+
217
+ /**
218
+ * Skip the import
219
+ *
220
+ * @returns {Boolean}
221
+ */
222
+ skip_import: function () {
223
+ MailPoet.Ajax.post({
224
+ api_version: window.mailpoet_api_version,
225
+ endpoint: 'MP2Migrator',
226
+ action: 'skipImport',
227
+ data: {
228
+ }
229
+ }).done(function () {
230
+ window.location.reload();
231
+ });
232
+ return false;
233
+ }
234
+
235
+ };
236
+
237
+ /**
238
+ * Actions to run when the DOM is ready
239
+ */
240
+ $(function () {
241
+ that = mailpoet_import;
242
+
243
+ $('#progressbar').progressbar({value: 0});
244
+
245
+ // Import button
246
+ $('#import').click(that.start_import);
247
+
248
+ // Stop import button
249
+ $('#stop-import').click(that.stop_import);
250
+
251
+ // Skip import link
252
+ $('#skip-import').click(that.skip_import);
253
+ });
254
+
255
+ })(jQuery);
256
+
257
+
258
+ /***/ }
259
+ /******/ ]);
assets/js/public.js CHANGED
@@ -1948,7 +1948,7 @@
1948
 
1949
  /* WEBPACK VAR INJECTION */(function(global) {/*!
1950
  * Parsley.js
1951
- * Version 2.7.0 - built Wed, Mar 1st 2017, 3:53 pm
1952
  * http://parsleyjs.org
1953
  * Guillaume Potier - <guillaume@wisembly.com>
1954
  * Marc-Andre Lafortune - <petroselinum@marc-andre.ca>
@@ -1962,6 +1962,8 @@
1962
 
1963
  var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })();
1964
 
 
 
1965
  function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }
1966
 
1967
  (function (global, factory) {
@@ -1972,10 +1974,10 @@
1972
  var globalID = 1;
1973
  var pastWarnings = {};
1974
 
1975
- var Utils__Utils = {
1976
  // Parsley DOM-API
1977
  // returns object from dom attributes and values
1978
- attr: function attr($element, namespace, obj) {
1979
  var i;
1980
  var attribute;
1981
  var attributes;
@@ -1988,9 +1990,9 @@
1988
  }
1989
  }
1990
 
1991
- if ('undefined' === typeof $element || 'undefined' === typeof $element[0]) return obj;
1992
 
1993
- attributes = $element[0].attributes;
1994
  for (i = attributes.length; i--;) {
1995
  attribute = attributes[i];
1996
 
@@ -2002,12 +2004,12 @@
2002
  return obj;
2003
  },
2004
 
2005
- checkAttr: function checkAttr($element, namespace, _checkAttr) {
2006
- return $element.is('[' + namespace + _checkAttr + ']');
2007
  },
2008
 
2009
- setAttr: function setAttr($element, namespace, attr, value) {
2010
- $element[0].setAttribute(this.dasherize(namespace + attr), String(value));
2011
  },
2012
 
2013
  generateID: function generateID() {
@@ -2094,7 +2096,7 @@
2094
  return !/^\s*false\s*$/i.test(string);
2095
  },
2096
  object: function object(string) {
2097
- return Utils__Utils.deserializeValue(string);
2098
  },
2099
  regexp: function regexp(_regexp) {
2100
  var flags = '';
@@ -2166,8 +2168,6 @@
2166
  _SubmitSelector: 'input[type="submit"], button:submit'
2167
  };
2168
 
2169
- var Utils__default = Utils__Utils;
2170
-
2171
  // All these options could be overriden and specified directly in DOM using
2172
  // `data-parsley-` default DOM-API
2173
  // eg: `inputs` can be set in DOM using `data-parsley-inputs="input, textarea"`
@@ -2234,7 +2234,7 @@
2234
  };
2235
 
2236
  var Base = function Base() {
2237
- this.__id__ = Utils__default.generateID();
2238
  };
2239
 
2240
  Base.prototype = {
@@ -2252,14 +2252,14 @@
2252
  },
2253
 
2254
  actualizeOptions: function actualizeOptions() {
2255
- Utils__default.attr(this.$element, this.options.namespace, this.domOptions);
2256
  if (this.parent && this.parent.actualizeOptions) this.parent.actualizeOptions();
2257
  return this;
2258
  },
2259
 
2260
  _resetOptions: function _resetOptions(initOptions) {
2261
- this.domOptions = Utils__default.objectCreate(this.parent.options);
2262
- this.options = Utils__default.objectCreate(this.domOptions);
2263
  // Shallow copy of ownProperties of initOptions:
2264
  for (var i in initOptions) {
2265
  if (initOptions.hasOwnProperty(i)) this.options[i] = initOptions[i];
@@ -2325,19 +2325,19 @@
2325
  },
2326
 
2327
  asyncIsValid: function asyncIsValid(group, force) {
2328
- Utils__default.warnOnce("asyncIsValid is deprecated; please use whenValid instead");
2329
  return this.whenValid({ group: group, force: force });
2330
  },
2331
 
2332
  _findRelated: function _findRelated() {
2333
- return this.options.multiple ? this.parent.$element.find('[' + this.options.namespace + 'multiple="' + this.options.multiple + '"]') : this.$element;
2334
  }
2335
  };
2336
 
2337
  var convertArrayRequirement = function convertArrayRequirement(string, length) {
2338
  var m = string.match(/^\s*\[(.*)\]\s*$/);
2339
  if (!m) throw 'Requirement is not an array: "' + string + '"';
2340
- var values = m[1].split(',').map(Utils__default.trimString);
2341
  if (values.length !== length) throw 'Requirement has ' + values.length + ' values when ' + length + ' are needed';
2342
  return values;
2343
  };
@@ -2348,10 +2348,10 @@
2348
  for (var key in requirementSpec) {
2349
  if (key) {
2350
  var value = extraOptionReader(key);
2351
- if ('string' === typeof value) value = Utils__default.parseRequirement(requirementSpec[key], value);
2352
  extra[key] = value;
2353
  } else {
2354
- main = Utils__default.parseRequirement(requirementSpec[key], string);
2355
  }
2356
  }
2357
  return [main, extra];
@@ -2374,13 +2374,13 @@
2374
  return this.fn(value, requirementFirstArg);
2375
  }
2376
 
2377
- if ($.isArray(value)) {
2378
  if (!this.validateMultiple) throw 'Validator `' + this.name + '` does not handle multiple values';
2379
  return this.validateMultiple.apply(this, arguments);
2380
  } else {
2381
  var instance = arguments[arguments.length - 1];
2382
  if (this.validateDate && instance._isDateInput()) {
2383
- arguments[0] = Utils__default.parse.date(arguments[0]);
2384
  if (arguments[0] === null) return false;
2385
  return this.validateDate.apply(this, arguments);
2386
  }
@@ -2402,17 +2402,17 @@
2402
  if ('string' !== typeof requirements) {
2403
  // Assume requirement already parsed
2404
  // but make sure we return an array
2405
- return $.isArray(requirements) ? requirements : [requirements];
2406
  }
2407
  var type = this.requirementType;
2408
- if ($.isArray(type)) {
2409
  var values = convertArrayRequirement(requirements, type.length);
2410
- for (var i = 0; i < values.length; i++) values[i] = Utils__default.parseRequirement(type[i], values[i]);
2411
  return values;
2412
  } else if ($.isPlainObject(type)) {
2413
  return convertExtraOptionRequirement(type, requirements, extraOptionReader);
2414
  } else {
2415
- return [Utils__default.parseRequirement(type, requirements)];
2416
  }
2417
  },
2418
  // Defaults:
@@ -2445,7 +2445,7 @@
2445
 
2446
  date: {
2447
  test: function test(value) {
2448
- return Utils__default.parse.date(value) !== null;
2449
  }
2450
  },
2451
 
@@ -2493,7 +2493,7 @@
2493
 
2494
  // parseArguments('number', ['1', '2']) => [1, 2]
2495
  var ValidatorRegistry__parseArguments = function ValidatorRegistry__parseArguments(type, args) {
2496
- return args.map(Utils__default.parse[type]);
2497
  };
2498
  // operatorToValidator returns a validating function for an operator function, applied to the given type
2499
  var ValidatorRegistry__operatorToValidator = function ValidatorRegistry__operatorToValidator(type, operator) {
@@ -2520,7 +2520,7 @@
2520
  init: function init(validators, catalog) {
2521
  this.catalog = catalog;
2522
  // Copy prototype's validators:
2523
- this.validators = $.extend({}, this.validators);
2524
 
2525
  for (var name in validators) this.addValidator(name, validators[name].fn, validators[name].priority);
2526
 
@@ -2576,8 +2576,8 @@
2576
  // Old API was addValidator(name, function, priority)
2577
  //
2578
  addValidator: function addValidator(name, arg1, arg2) {
2579
- if (this.validators[name]) Utils__default.warn('Validator "' + name + '" is already defined.');else if (Defaults.hasOwnProperty(name)) {
2580
- Utils__default.warn('"' + name + '" is a restricted keyword and is not a valid validator name.');
2581
  return;
2582
  }
2583
  return this._setValidator.apply(this, arguments);
@@ -2585,14 +2585,14 @@
2585
 
2586
  updateValidator: function updateValidator(name, arg1, arg2) {
2587
  if (!this.validators[name]) {
2588
- Utils__default.warn('Validator "' + name + '" is not already defined.');
2589
  return this.addValidator.apply(this, arguments);
2590
  }
2591
  return this._setValidator.apply(this, arguments);
2592
  },
2593
 
2594
  removeValidator: function removeValidator(name) {
2595
- if (!this.validators[name]) Utils__default.warn('Validator "' + name + '" is not defined.');
2596
 
2597
  delete this.validators[name];
2598
 
@@ -2801,14 +2801,14 @@
2801
  this.$element.on('submit.Parsley', function (evt) {
2802
  _this2.onSubmitValidate(evt);
2803
  });
2804
- this.$element.on('click.Parsley', Utils__default._SubmitSelector, function (evt) {
2805
  _this2.onSubmitButton(evt);
2806
  });
2807
 
2808
  // UI could be disabled
2809
  if (false === this.options.uiEnabled) return;
2810
 
2811
- this.$element.attr('novalidate', '');
2812
  },
2813
 
2814
  focus: function focus() {
@@ -2985,7 +2985,7 @@
2985
  var _ui = {};
2986
 
2987
  // Give field its Parsley id in DOM
2988
- this.$element.attr(this.options.namespace + 'id', this.__id__);
2989
 
2990
  /** Generate important UI elements and store them in this **/
2991
  // $errorClassHandler is the $element that woul have parsley-error and parsley-success classes
@@ -3006,10 +3006,15 @@
3006
  // Determine which element will have `parsley-error` and `parsley-success` classes
3007
  _manageClassHandler: function _manageClassHandler() {
3008
  // An element selector could be passed through DOM with `data-parsley-class-handler=#foo`
3009
- if ('string' === typeof this.options.classHandler && $(this.options.classHandler).length) return $(this.options.classHandler);
 
 
 
 
 
3010
 
3011
  // Class handled could also be determined by function given in Parsley options
3012
- var $handler = this.options.classHandler.call(this, this);
3013
 
3014
  // If this function returned a valid existing DOM element, go for it
3015
  if ('undefined' !== typeof $handler && $handler.length) return $handler;
@@ -3019,7 +3024,7 @@
3019
 
3020
  _inputHolder: function _inputHolder() {
3021
  // if simple element (input, texatrea, select...) it will perfectly host the classes and precede the error container
3022
- if (!this.options.multiple || this.$element.is('select')) return this.$element;
3023
 
3024
  // But if multiple element (radio, checkbox), that would be their parent
3025
  return this.$element.parent();
@@ -3032,7 +3037,7 @@
3032
  if (0 !== this._ui.$errorsWrapper.parent().length) return this._ui.$errorsWrapper.parent();
3033
 
3034
  if ('string' === typeof this.options.errorsContainer) {
3035
- if ($(this.options.errorsContainer).length) return $(this.options.errorsContainer).append(this._ui.$errorsWrapper);else Utils__default.warn('The errors container `' + this.options.errorsContainer + '` does not exist in DOM');
3036
  } else if ('function' === typeof this.options.errorsContainer) $errorsContainer = this.options.errorsContainer.call(this, this);
3037
 
3038
  if ('undefined' !== typeof $errorsContainer && $errorsContainer.length) return $errorsContainer.append(this._ui.$errorsWrapper);
@@ -3048,9 +3053,9 @@
3048
 
3049
  // Remove Parsley events already bound on this field
3050
  $toBind.off('.Parsley');
3051
- if (this._failedOnce) $toBind.on(Utils__default.namespaceEvents(this.options.triggerAfterFailure, 'Parsley'), function () {
3052
  _this3._validateIfNeeded();
3053
- });else if (trigger = Utils__default.namespaceEvents(this.options.trigger, 'Parsley')) {
3054
  $toBind.on(trigger, function (event) {
3055
  _this3._validateIfNeeded(event);
3056
  });
@@ -3116,6 +3121,7 @@
3116
  var Form = function Form(element, domOptions, options) {
3117
  this.__class__ = 'Form';
3118
 
 
3119
  this.$element = $(element);
3120
  this.domOptions = domOptions;
3121
  this.options = options;
@@ -3135,10 +3141,12 @@
3135
  if (true === event.parsley) return;
3136
 
3137
  // If we didn't come here through a submit button, use the first one in the form
3138
- var $submitSource = this._$submitSource || this.$element.find(Utils__default._SubmitSelector).first();
3139
- this._$submitSource = null;
3140
  this.$element.find('.parsley-synthetic-submit-button').prop('disabled', true);
3141
- if ($submitSource.is('[formnovalidate]')) return;
 
 
3142
 
3143
  var promise = this.whenValidate({ event: event });
3144
 
@@ -3150,30 +3158,30 @@
3150
  event.stopImmediatePropagation();
3151
  event.preventDefault();
3152
  if ('pending' === promise.state()) promise.done(function () {
3153
- _this5._submit($submitSource);
3154
  });
3155
  }
3156
  },
3157
 
3158
  onSubmitButton: function onSubmitButton(event) {
3159
- this._$submitSource = $(event.currentTarget);
3160
  },
3161
  // internal
3162
  // _submit submits the form, this time without going through the validations.
3163
  // Care must be taken to "fake" the actual submit button being clicked.
3164
- _submit: function _submit($submitSource) {
3165
  if (false === this._trigger('submit')) return;
3166
  // Add submit button's data
3167
- if ($submitSource) {
3168
  var $synthetic = this.$element.find('.parsley-synthetic-submit-button').prop('disabled', false);
3169
  if (0 === $synthetic.length) $synthetic = $('<input class="parsley-synthetic-submit-button" type="hidden">').appendTo(this.$element);
3170
  $synthetic.attr({
3171
- name: $submitSource.attr('name'),
3172
- value: $submitSource.attr('value')
3173
  });
3174
  }
3175
 
3176
- this.$element.trigger($.extend($.Event('submit'), { parsley: true }));
3177
  },
3178
 
3179
  // Performs validation on fields while triggering events.
@@ -3183,7 +3191,7 @@
3183
  // Consider using `whenValidate` instead.
3184
  validate: function validate(options) {
3185
  if (arguments.length >= 1 && !$.isPlainObject(options)) {
3186
- Utils__default.warnOnce('Calling validate on a parsley form without passing arguments as an object is deprecated.');
3187
 
3188
  var _arguments = _slice.call(arguments);
3189
 
@@ -3197,7 +3205,7 @@
3197
  },
3198
 
3199
  whenValidate: function whenValidate() {
3200
- var _Utils__default$all$done$fail$always,
3201
  _this6 = this;
3202
 
3203
  var _ref7 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
@@ -3208,8 +3216,8 @@
3208
 
3209
  this.submitEvent = event;
3210
  if (event) {
3211
- this.submitEvent = $.extend({}, event, { preventDefault: function preventDefault() {
3212
- Utils__default.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`");
3213
  _this6.validationResult = false;
3214
  } });
3215
  }
@@ -3227,7 +3235,7 @@
3227
  });
3228
  });
3229
 
3230
- return (_Utils__default$all$done$fail$always = Utils__default.all(promises).done(function () {
3231
  _this6._trigger('success');
3232
  }).fail(function () {
3233
  _this6.validationResult = false;
@@ -3235,7 +3243,7 @@
3235
  _this6._trigger('error');
3236
  }).always(function () {
3237
  _this6._trigger('validated');
3238
- })).pipe.apply(_Utils__default$all$done$fail$always, _toConsumableArray(this._pipeAccordingToValidationResult()));
3239
  },
3240
 
3241
  // Iterate over refreshed fields, and stop on first failure.
@@ -3244,7 +3252,7 @@
3244
  // Prefer using `whenValid` instead.
3245
  isValid: function isValid(options) {
3246
  if (arguments.length >= 1 && !$.isPlainObject(options)) {
3247
- Utils__default.warnOnce('Calling isValid on a parsley form without passing arguments as an object is deprecated.');
3248
 
3249
  var _arguments2 = _slice.call(arguments);
3250
 
@@ -3274,7 +3282,7 @@
3274
  return field.whenValid({ group: group, force: force });
3275
  });
3276
  });
3277
- return Utils__default.all(promises);
3278
  },
3279
 
3280
  // Reset UI
@@ -3323,7 +3331,7 @@
3323
  }
3324
  });
3325
 
3326
- $.each(Utils__default.difference(oldFields, _this8.fields), function (_, field) {
3327
  field.reset();
3328
  });
3329
  });
@@ -3359,13 +3367,15 @@
3359
  var Constraint = function Constraint(parsleyField, name, requirements, priority, isDomConstraint) {
3360
  var validatorSpec = window.Parsley._validatorRegistry.validators[name];
3361
  var validator = new Validator(validatorSpec);
 
 
3362
 
3363
- $.extend(this, {
3364
  validator: validator,
3365
  name: name,
3366
  requirements: requirements,
3367
- priority: priority || parsleyField.options[name + 'Priority'] || validator.priority,
3368
- isDomConstraint: true === isDomConstraint
3369
  });
3370
  this._parseRequirements(parsleyField.options);
3371
  };
@@ -3394,6 +3404,7 @@
3394
  var Field = function Field(field, domOptions, options, parsleyFormInstance) {
3395
  this.__class__ = 'Field';
3396
 
 
3397
  this.$element = $(field);
3398
 
3399
  // Set parent if we have one
@@ -3422,7 +3433,7 @@
3422
  // `null` if validation is not finished. Prefer using whenValidate
3423
  validate: function validate(options) {
3424
  if (arguments.length >= 1 && !$.isPlainObject(options)) {
3425
- Utils__default.warnOnce('Calling validate on a parsley field without passing arguments as an object is deprecated.');
3426
  options = { options: options };
3427
  }
3428
  var promise = this.whenValidate(options);
@@ -3486,7 +3497,7 @@
3486
  },
3487
 
3488
  _isInGroup: function _isInGroup(group) {
3489
- if ($.isArray(this.options.group)) return -1 !== $.inArray(group, this.options.group);
3490
  return this.options.group === group;
3491
  },
3492
 
@@ -3496,7 +3507,7 @@
3496
  // See also `whenValid`.
3497
  isValid: function isValid(options) {
3498
  if (arguments.length >= 1 && !$.isPlainObject(options)) {
3499
- Utils__default.warnOnce('Calling isValid on a parsley field without passing arguments as an object is deprecated.');
3500
 
3501
  var _arguments3 = _slice.call(arguments);
3502
 
@@ -3547,13 +3558,13 @@
3547
  $.each(groupedConstraints, function (_, constraints) {
3548
  // Process one group of constraints at a time, we validate the constraints
3549
  // and combine the promises together.
3550
- var promise = Utils__default.all($.map(constraints, function (constraint) {
3551
  return _this11._validateConstraint(value, constraint);
3552
  }));
3553
  promises.push(promise);
3554
  if (promise.state() === 'rejected') return false; // Interrupt processing if a group has already failed
3555
  });
3556
- return Utils__default.all(promises);
3557
  },
3558
 
3559
  // @returns a promise
@@ -3564,7 +3575,7 @@
3564
  // Map false to a failed promise
3565
  if (false === result) result = $.Deferred().reject();
3566
  // Make sure we return a promise and that we record failures
3567
- return Utils__default.all([result]).fail(function (errorMessage) {
3568
  if (!(_this12.validationResult instanceof Array)) _this12.validationResult = [];
3569
  _this12.validationResult.push({
3570
  assert: constraint,
@@ -3673,39 +3684,39 @@
3673
  // Bind specific HTML5 constraints to be HTML5 compliant
3674
  _bindHtml5Constraints: function _bindHtml5Constraints() {
3675
  // html5 required
3676
- if (this.$element.attr('required')) this.addConstraint('required', true, undefined, true);
3677
 
3678
  // html5 pattern
3679
- if ('string' === typeof this.$element.attr('pattern')) this.addConstraint('pattern', this.$element.attr('pattern'), undefined, true);
3680
 
3681
  // range
3682
- if ('undefined' !== typeof this.$element.attr('min') && 'undefined' !== typeof this.$element.attr('max')) this.addConstraint('range', [this.$element.attr('min'), this.$element.attr('max')], undefined, true);
 
 
3683
 
3684
  // HTML5 min
3685
- else if ('undefined' !== typeof this.$element.attr('min')) this.addConstraint('min', this.$element.attr('min'), undefined, true);
3686
 
3687
  // HTML5 max
3688
- else if ('undefined' !== typeof this.$element.attr('max')) this.addConstraint('max', this.$element.attr('max'), undefined, true);
3689
 
3690
  // length
3691
- if ('undefined' !== typeof this.$element.attr('minlength') && 'undefined' !== typeof this.$element.attr('maxlength')) this.addConstraint('length', [this.$element.attr('minlength'), this.$element.attr('maxlength')], undefined, true);
3692
 
3693
  // HTML5 minlength
3694
- else if ('undefined' !== typeof this.$element.attr('minlength')) this.addConstraint('minlength', this.$element.attr('minlength'), undefined, true);
3695
 
3696
  // HTML5 maxlength
3697
- else if ('undefined' !== typeof this.$element.attr('maxlength')) this.addConstraint('maxlength', this.$element.attr('maxlength'), undefined, true);
3698
 
3699
  // html5 types
3700
- var type = this.$element.attr('type');
3701
-
3702
- if ('undefined' === typeof type) return this;
3703
 
3704
  // Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise
3705
  if ('number' === type) {
3706
  return this.addConstraint('type', ['number', {
3707
- step: this.$element.attr('step') || '1',
3708
- base: this.$element.attr('min') || this.$element.attr('value')
3709
  }], undefined, true);
3710
  // Regular other HTML5 supported types
3711
  } else if (/^(email|url|range|date)$/i.test(type)) {
@@ -3733,11 +3744,11 @@
3733
  // Use `data-parsley-whitespace="squish"` to auto squish input value
3734
  // Use `data-parsley-whitespace="trim"` to auto trim input value
3735
  _handleWhitespace: function _handleWhitespace(value) {
3736
- if (true === this.options.trimValue) Utils__default.warnOnce('data-parsley-trim-value="true" is deprecated, please use data-parsley-whitespace="trim"');
3737
 
3738
  if ('squish' === this.options.whitespace) value = value.replace(/\s{2,}/g, ' ');
3739
 
3740
- if ('trim' === this.options.whitespace || 'squish' === this.options.whitespace || true === this.options.trimValue) value = Utils__default.trimString(value);
3741
 
3742
  return value;
3743
  },
@@ -3793,7 +3804,7 @@
3793
  this.constraints = [];
3794
 
3795
  // Select multiple special treatment
3796
- if (this.$element.is('select')) {
3797
  this.actualizeOptions()._bindConstraints();
3798
 
3799
  return this;
@@ -3822,21 +3833,23 @@
3822
  if ('function' === typeof this.options.value) return this.options.value(this);else if ('undefined' !== typeof this.options.value) return this.options.value;
3823
 
3824
  // Radio input case
3825
- if (this.$element.is('input[type=radio]')) return this._findRelated().filter(':checked').val() || '';
 
3826
 
3827
- // checkbox input case
3828
- if (this.$element.is('input[type=checkbox]')) {
3829
- var values = [];
3830
 
3831
- this._findRelated().filter(':checked').each(function () {
3832
- values.push($(this).val());
3833
- });
3834
 
3835
- return values;
 
3836
  }
3837
 
3838
  // Select multiple case
3839
- if (this.$element.is('select') && null === this.$element.val()) return [];
3840
 
3841
  // Default case that should never happen
3842
  return this.$element.val();
@@ -3850,6 +3863,7 @@
3850
  };
3851
 
3852
  var Factory = function Factory(element, options, parsleyFormInstance) {
 
3853
  this.$element = $(element);
3854
 
3855
  // If the element has already been bound, returns its saved Parsley instance
@@ -3863,7 +3877,7 @@
3863
  }
3864
 
3865
  if ('object' === typeof options) {
3866
- $.extend(savedparsleyFormInstance.options, options);
3867
  }
3868
 
3869
  return savedparsleyFormInstance;
@@ -3881,21 +3895,21 @@
3881
  Factory.prototype = {
3882
  init: function init(options) {
3883
  this.__class__ = 'Parsley';
3884
- this.__version__ = '2.7.0';
3885
- this.__id__ = Utils__default.generateID();
3886
 
3887
  // Pre-compute options
3888
  this._resetOptions(options);
3889
 
3890
  // A Form instance is obviously a `<form>` element but also every node that is not an input and has the `data-parsley-validate` attribute
3891
- if (this.$element.is('form') || Utils__default.checkAttr(this.$element, this.options.namespace, 'validate') && !this.$element.is(this.options.inputs)) return this.bind('parsleyForm');
3892
 
3893
  // Every other element is bound as a `Field` or `FieldMultiple`
3894
  return this.isMultiple() ? this.handleMultiple() : this.bind('parsleyField');
3895
  },
3896
 
3897
  isMultiple: function isMultiple() {
3898
- return this.$element.is('input[type=radio], input[type=checkbox]') || this.$element.is('select') && 'undefined' !== typeof this.$element.attr('multiple');
3899
  },
3900
 
3901
  // Multiples fields are a real nightmare :(
@@ -3908,17 +3922,16 @@
3908
  var parsleyMultipleInstance;
3909
 
3910
  // Handle multiple name
3911
- if (this.options.multiple) ; // We already have our 'multiple' identifier
3912
- else if ('undefined' !== typeof this.$element.attr('name') && this.$element.attr('name').length) this.options.multiple = name = this.$element.attr('name');else if ('undefined' !== typeof this.$element.attr('id') && this.$element.attr('id').length) this.options.multiple = this.$element.attr('id');
3913
 
3914
  // Special select multiple input
3915
- if (this.$element.is('select') && 'undefined' !== typeof this.$element.attr('multiple')) {
3916
  this.options.multiple = this.options.multiple || this.__id__;
3917
  return this.bind('parsleyFieldMultiple');
3918
 
3919
  // Else for radio / checkboxes, we need a `name` or `data-parsley-multiple` to properly bind it
3920
  } else if (!this.options.multiple) {
3921
- Utils__default.warn('To be bound by Parsley, a radio, a checkbox and a multiple select input must have either a name or a multiple option.', this.$element);
3922
  return this;
3923
  }
3924
 
@@ -3926,9 +3939,9 @@
3926
  this.options.multiple = this.options.multiple.replace(/(:|\.|\[|\]|\{|\}|\$)/g, '');
3927
 
3928
  // Add proper `data-parsley-multiple` to siblings if we have a valid multiple name
3929
- if ('undefined' !== typeof name) {
3930
  $('input[name="' + name + '"]').each(function (i, input) {
3931
- if ($(input).is('input[type=radio], input[type=checkbox]')) $(input).attr(_this13.options.namespace + 'multiple', _this13.options.multiple);
3932
  });
3933
  }
3934
 
@@ -3959,19 +3972,19 @@
3959
 
3960
  switch (type) {
3961
  case 'parsleyForm':
3962
- parsleyInstance = $.extend(new Form(this.$element, this.domOptions, this.options), new Base(), window.ParsleyExtend)._bindFields();
3963
  break;
3964
  case 'parsleyField':
3965
- parsleyInstance = $.extend(new parsley_field(this.$element, this.domOptions, this.options, this.parent), new Base(), window.ParsleyExtend);
3966
  break;
3967
  case 'parsleyFieldMultiple':
3968
- parsleyInstance = $.extend(new parsley_field(this.$element, this.domOptions, this.options, this.parent), new Multiple(), new Base(), window.ParsleyExtend)._init();
3969
  break;
3970
  default:
3971
  throw new Error(type + 'is not a supported Parsley type');
3972
  }
3973
 
3974
- if (this.options.multiple) Utils__default.setAttr(this.$element, this.options.namespace, 'multiple', this.options.multiple);
3975
 
3976
  if ('undefined' !== typeof doNotStore) {
3977
  this.$element.data('FieldMultiple', parsleyInstance);
@@ -3995,23 +4008,24 @@
3995
  throw "The loaded version of jQuery is too old. Please upgrade to 1.8.x or better.";
3996
  }
3997
  if (!vernums.forEach) {
3998
- Utils__default.warn('Parsley requires ES5 to run properly. Please include https://github.com/es-shims/es5-shim');
3999
  }
4000
  // Inherit `on`, `off` & `trigger` to Parsley:
4001
- var Parsley = $.extend(new Base(), {
 
4002
  $element: $(document),
4003
  actualizeOptions: null,
4004
  _resetOptions: null,
4005
  Factory: Factory,
4006
- version: '2.7.0'
4007
  });
4008
 
4009
  // Supplement Field and Form with Base
4010
  // This way, the constructors will have access to those methods
4011
- $.extend(parsley_field.prototype, UI.Field, Base.prototype);
4012
- $.extend(Form.prototype, UI.Form, Base.prototype);
4013
  // Inherit actualizeOptions and _resetOptions:
4014
- $.extend(Factory.prototype, Base.prototype);
4015
 
4016
  // ### jQuery API
4017
  // `$('.elem').parsley(options)` or `$('.elem').psly(options)`
@@ -4028,12 +4042,12 @@
4028
 
4029
  // Return undefined if applied to non existing DOM element
4030
  if (!$(this).length) {
4031
- Utils__default.warn('You must bind Parsley on an existing element.');
4032
 
4033
  return;
4034
  }
4035
 
4036
- return new Factory(this, options);
4037
  };
4038
 
4039
  // ### Field and Form extension
@@ -4042,18 +4056,18 @@
4042
 
4043
  // ### Parsley config
4044
  // Inherit from ParsleyDefault, and copy over any existing values
4045
- Parsley.options = $.extend(Utils__default.objectCreate(Defaults), window.ParsleyConfig);
4046
  window.ParsleyConfig = Parsley.options; // Old way of accessing global options
4047
 
4048
  // ### Globals
4049
  window.Parsley = window.psly = Parsley;
4050
- Parsley.Utils = Utils__default;
4051
  window.ParsleyUtils = {};
4052
- $.each(Utils__default, function (key, value) {
4053
  if ('function' === typeof value) {
4054
  window.ParsleyUtils[key] = function () {
4055
- Utils__default.warnOnce('Accessing `window.ParsleyUtils` is deprecated. Use `window.Parsley.Utils` instead.');
4056
- return Utils__default[key].apply(Utils__default, arguments);
4057
  };
4058
  }
4059
  });
@@ -4062,11 +4076,13 @@
4062
  var registry = window.Parsley._validatorRegistry = new ValidatorRegistry(window.ParsleyConfig.validators, window.ParsleyConfig.i18n);
4063
  window.ParsleyValidator = {};
4064
  $.each('setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator'.split(' '), function (i, method) {
4065
- window.Parsley[method] = $.proxy(registry, method);
 
 
4066
  window.ParsleyValidator[method] = function () {
4067
  var _window$Parsley;
4068
 
4069
- Utils__default.warnOnce('Accessing the method \'' + method + '\' through Validator is deprecated. Simply call \'window.Parsley.' + method + '(...)\'');
4070
  return (_window$Parsley = window.Parsley)[method].apply(_window$Parsley, arguments);
4071
  };
4072
  });
@@ -4077,18 +4093,18 @@
4077
  window.ParsleyUI = {
4078
  removeError: function removeError(instance, name, doNotUpdateClass) {
4079
  var updateClass = true !== doNotUpdateClass;
4080
- Utils__default.warnOnce('Accessing UI is deprecated. Call \'removeError\' on the instance directly. Please comment in issue 1073 as to your need to call this method.');
4081
  return instance.removeError(name, { updateClass: updateClass });
4082
  },
4083
  getErrorsMessages: function getErrorsMessages(instance) {
4084
- Utils__default.warnOnce('Accessing UI is deprecated. Call \'getErrorsMessages\' on the instance directly.');
4085
  return instance.getErrorsMessages();
4086
  }
4087
  };
4088
  $.each('addError updateError'.split(' '), function (i, method) {
4089
  window.ParsleyUI[method] = function (instance, name, message, assert, doNotUpdateClass) {
4090
  var updateClass = true !== doNotUpdateClass;
4091
- Utils__default.warnOnce('Accessing UI is deprecated. Call \'' + method + '\' on the instance directly. Please comment in issue 1073 as to your need to call this method.');
4092
  return instance[method](name, { message: message, assert: assert, updateClass: updateClass });
4093
  };
4094
  });
@@ -4104,7 +4120,7 @@
4104
 
4105
  var o = $({});
4106
  var deprecated = function deprecated() {
4107
- Utils__default.warnOnce("Parsley's pubsub module is deprecated; use the 'on' and 'off' methods on parsley instances or window.Parsley");
4108
  };
4109
 
4110
  // Returns an event handler that calls `fn` with the arguments it expects
@@ -4244,7 +4260,7 @@
4244
  if (url.indexOf('{value}') > -1) {
4245
  url = url.replace('{value}', encodeURIComponent(value));
4246
  } else {
4247
- data[instance.$element.attr('name') || instance.$element.attr('id')] = value;
4248
  }
4249
 
4250
  // Merge options passed in from the function with the ones in the attribute
@@ -4285,7 +4301,7 @@
4285
  Parsley._remoteCache = {};
4286
  });
4287
 
4288
- window.ParsleyExtend.addAsyncValidator = function () {
4289
  Utils.warnOnce('Accessing the method `addAsyncValidator` through an instance is deprecated. Simply call `Parsley.addAsyncValidator(...)`');
4290
  return Parsley.addAsyncValidator.apply(Parsley, arguments);
4291
  };
@@ -4334,7 +4350,7 @@
4334
 
4335
  // Slightly odd way construct our object. This way methods are force bound.
4336
  // Used to test for duplicate library.
4337
- $.extend(this, {
4338
 
4339
  // For browsers that do not support isTrusted, assumes event is native.
4340
  isNativeEvent: function isNativeEvent(evt) {
1948
 
1949
  /* WEBPACK VAR INJECTION */(function(global) {/*!
1950
  * Parsley.js
1951
+ * Version 2.7.2 - built Tue, May 9th 2017, 11:21 am
1952
  * http://parsleyjs.org
1953
  * Guillaume Potier - <guillaume@wisembly.com>
1954
  * Marc-Andre Lafortune - <petroselinum@marc-andre.ca>
1962
 
1963
  var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })();
1964
 
1965
+ var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
1966
+
1967
  function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }
1968
 
1969
  (function (global, factory) {
1974
  var globalID = 1;
1975
  var pastWarnings = {};
1976
 
1977
+ var Utils = {
1978
  // Parsley DOM-API
1979
  // returns object from dom attributes and values
1980
+ attr: function attr(element, namespace, obj) {
1981
  var i;
1982
  var attribute;
1983
  var attributes;
1990
  }
1991
  }
1992
 
1993
+ if (!element) return obj;
1994
 
1995
+ attributes = element.attributes;
1996
  for (i = attributes.length; i--;) {
1997
  attribute = attributes[i];
1998
 
2004
  return obj;
2005
  },
2006
 
2007
+ checkAttr: function checkAttr(element, namespace, _checkAttr) {
2008
+ return element.hasAttribute(namespace + _checkAttr);
2009
  },
2010
 
2011
+ setAttr: function setAttr(element, namespace, attr, value) {
2012
+ element.setAttribute(this.dasherize(namespace + attr), String(value));
2013
  },
2014
 
2015
  generateID: function generateID() {
2096
  return !/^\s*false\s*$/i.test(string);
2097
  },
2098
  object: function object(string) {
2099
+ return Utils.deserializeValue(string);
2100
  },
2101
  regexp: function regexp(_regexp) {
2102
  var flags = '';
2168
  _SubmitSelector: 'input[type="submit"], button:submit'
2169
  };
2170
 
 
 
2171
  // All these options could be overriden and specified directly in DOM using
2172
  // `data-parsley-` default DOM-API
2173
  // eg: `inputs` can be set in DOM using `data-parsley-inputs="input, textarea"`
2234
  };
2235
 
2236
  var Base = function Base() {
2237
+ this.__id__ = Utils.generateID();
2238
  };
2239
 
2240
  Base.prototype = {
2252
  },
2253
 
2254
  actualizeOptions: function actualizeOptions() {
2255
+ Utils.attr(this.element, this.options.namespace, this.domOptions);
2256
  if (this.parent && this.parent.actualizeOptions) this.parent.actualizeOptions();
2257
  return this;
2258
  },
2259
 
2260
  _resetOptions: function _resetOptions(initOptions) {
2261
+ this.domOptions = Utils.objectCreate(this.parent.options);
2262
+ this.options = Utils.objectCreate(this.domOptions);
2263
  // Shallow copy of ownProperties of initOptions:
2264
  for (var i in initOptions) {
2265
  if (initOptions.hasOwnProperty(i)) this.options[i] = initOptions[i];
2325
  },
2326
 
2327
  asyncIsValid: function asyncIsValid(group, force) {
2328
+ Utils.warnOnce("asyncIsValid is deprecated; please use whenValid instead");
2329
  return this.whenValid({ group: group, force: force });
2330
  },
2331
 
2332
  _findRelated: function _findRelated() {
2333
+ return this.options.multiple ? $(this.parent.element.querySelectorAll('[' + this.options.namespace + 'multiple="' + this.options.multiple + '"]')) : this.$element;
2334
  }
2335
  };
2336
 
2337
  var convertArrayRequirement = function convertArrayRequirement(string, length) {
2338
  var m = string.match(/^\s*\[(.*)\]\s*$/);
2339
  if (!m) throw 'Requirement is not an array: "' + string + '"';
2340
+ var values = m[1].split(',').map(Utils.trimString);
2341
  if (values.length !== length) throw 'Requirement has ' + values.length + ' values when ' + length + ' are needed';
2342
  return values;
2343
  };
2348
  for (var key in requirementSpec) {
2349
  if (key) {
2350
  var value = extraOptionReader(key);
2351
+ if ('string' === typeof value) value = Utils.parseRequirement(requirementSpec[key], value);
2352
  extra[key] = value;
2353
  } else {
2354
+ main = Utils.parseRequirement(requirementSpec[key], string);
2355
  }
2356
  }
2357
  return [main, extra];
2374
  return this.fn(value, requirementFirstArg);
2375
  }
2376
 
2377
+ if (Array.isArray(value)) {
2378
  if (!this.validateMultiple) throw 'Validator `' + this.name + '` does not handle multiple values';
2379
  return this.validateMultiple.apply(this, arguments);
2380
  } else {
2381
  var instance = arguments[arguments.length - 1];
2382
  if (this.validateDate && instance._isDateInput()) {
2383
+ arguments[0] = Utils.parse.date(arguments[0]);
2384
  if (arguments[0] === null) return false;
2385
  return this.validateDate.apply(this, arguments);
2386
  }
2402
  if ('string' !== typeof requirements) {
2403
  // Assume requirement already parsed
2404
  // but make sure we return an array
2405
+ return Array.isArray(requirements) ? requirements : [requirements];
2406
  }
2407
  var type = this.requirementType;
2408
+ if (Array.isArray(type)) {
2409
  var values = convertArrayRequirement(requirements, type.length);
2410
+ for (var i = 0; i < values.length; i++) values[i] = Utils.parseRequirement(type[i], values[i]);
2411
  return values;
2412
  } else if ($.isPlainObject(type)) {
2413
  return convertExtraOptionRequirement(type, requirements, extraOptionReader);
2414
  } else {
2415
+ return [Utils.parseRequirement(type, requirements)];
2416
  }
2417
  },
2418
  // Defaults:
2445
 
2446
  date: {
2447
  test: function test(value) {
2448
+ return Utils.parse.date(value) !== null;
2449
  }
2450
  },
2451
 
2493
 
2494
  // parseArguments('number', ['1', '2']) => [1, 2]
2495
  var ValidatorRegistry__parseArguments = function ValidatorRegistry__parseArguments(type, args) {
2496
+ return args.map(Utils.parse[type]);
2497
  };
2498
  // operatorToValidator returns a validating function for an operator function, applied to the given type
2499
  var ValidatorRegistry__operatorToValidator = function ValidatorRegistry__operatorToValidator(type, operator) {
2520
  init: function init(validators, catalog) {
2521
  this.catalog = catalog;
2522
  // Copy prototype's validators:
2523
+ this.validators = _extends({}, this.validators);
2524
 
2525
  for (var name in validators) this.addValidator(name, validators[name].fn, validators[name].priority);
2526
 
2576
  // Old API was addValidator(name, function, priority)
2577
  //
2578
  addValidator: function addValidator(name, arg1, arg2) {
2579
+ if (this.validators[name]) Utils.warn('Validator "' + name + '" is already defined.');else if (Defaults.hasOwnProperty(name)) {
2580
+ Utils.warn('"' + name + '" is a restricted keyword and is not a valid validator name.');
2581
  return;
2582
  }
2583
  return this._setValidator.apply(this, arguments);
2585
 
2586
  updateValidator: function updateValidator(name, arg1, arg2) {
2587
  if (!this.validators[name]) {
2588
+ Utils.warn('Validator "' + name + '" is not already defined.');
2589
  return this.addValidator.apply(this, arguments);
2590
  }
2591
  return this._setValidator.apply(this, arguments);
2592
  },
2593
 
2594
  removeValidator: function removeValidator(name) {
2595
+ if (!this.validators[name]) Utils.warn('Validator "' + name + '" is not defined.');
2596
 
2597
  delete this.validators[name];
2598
 
2801
  this.$element.on('submit.Parsley', function (evt) {
2802
  _this2.onSubmitValidate(evt);
2803
  });
2804
+ this.$element.on('click.Parsley', Utils._SubmitSelector, function (evt) {
2805
  _this2.onSubmitButton(evt);
2806
  });
2807
 
2808
  // UI could be disabled
2809
  if (false === this.options.uiEnabled) return;
2810
 
2811
+ this.element.setAttribute('novalidate', '');
2812
  },
2813
 
2814
  focus: function focus() {
2985
  var _ui = {};
2986
 
2987
  // Give field its Parsley id in DOM
2988
+ this.element.setAttribute(this.options.namespace + 'id', this.__id__);
2989
 
2990
  /** Generate important UI elements and store them in this **/
2991
  // $errorClassHandler is the $element that woul have parsley-error and parsley-success classes
3006
  // Determine which element will have `parsley-error` and `parsley-success` classes
3007
  _manageClassHandler: function _manageClassHandler() {
3008
  // An element selector could be passed through DOM with `data-parsley-class-handler=#foo`
3009
+ if ('string' === typeof this.options.classHandler) {
3010
+ if ($(this.options.classHandler).length === 0) ParsleyUtils.warn('No elements found that match the selector `' + this.options.classHandler + '` set in options.classHandler or data-parsley-class-handler');
3011
+
3012
+ //return element or empty set
3013
+ return $(this.options.classHandler);
3014
+ }
3015
 
3016
  // Class handled could also be determined by function given in Parsley options
3017
+ if ('function' === typeof this.options.classHandler) var $handler = this.options.classHandler.call(this, this);
3018
 
3019
  // If this function returned a valid existing DOM element, go for it
3020
  if ('undefined' !== typeof $handler && $handler.length) return $handler;
3024
 
3025
  _inputHolder: function _inputHolder() {
3026
  // if simple element (input, texatrea, select...) it will perfectly host the classes and precede the error container
3027
+ if (!this.options.multiple || this.element.nodeName === 'SELECT') return this.$element;
3028
 
3029
  // But if multiple element (radio, checkbox), that would be their parent
3030
  return this.$element.parent();
3037
  if (0 !== this._ui.$errorsWrapper.parent().length) return this._ui.$errorsWrapper.parent();
3038
 
3039
  if ('string' === typeof this.options.errorsContainer) {
3040
+ if ($(this.options.errorsContainer).length) return $(this.options.errorsContainer).append(this._ui.$errorsWrapper);else Utils.warn('The errors container `' + this.options.errorsContainer + '` does not exist in DOM');
3041
  } else if ('function' === typeof this.options.errorsContainer) $errorsContainer = this.options.errorsContainer.call(this, this);
3042
 
3043
  if ('undefined' !== typeof $errorsContainer && $errorsContainer.length) return $errorsContainer.append(this._ui.$errorsWrapper);
3053
 
3054
  // Remove Parsley events already bound on this field
3055
  $toBind.off('.Parsley');
3056
+ if (this._failedOnce) $toBind.on(Utils.namespaceEvents(this.options.triggerAfterFailure, 'Parsley'), function () {
3057
  _this3._validateIfNeeded();
3058
+ });else if (trigger = Utils.namespaceEvents(this.options.trigger, 'Parsley')) {
3059
  $toBind.on(trigger, function (event) {
3060
  _this3._validateIfNeeded(event);
3061
  });
3121
  var Form = function Form(element, domOptions, options) {
3122
  this.__class__ = 'Form';
3123
 
3124
+ this.element = element;
3125
  this.$element = $(element);
3126
  this.domOptions = domOptions;
3127
  this.options = options;
3141
  if (true === event.parsley) return;
3142
 
3143
  // If we didn't come here through a submit button, use the first one in the form
3144
+ var submitSource = this._submitSource || this.$element.find(Utils._SubmitSelector)[0];
3145
+ this._submitSource = null;
3146
  this.$element.find('.parsley-synthetic-submit-button').prop('disabled', true);
3147
+ if (submitSource && null !== submitSource.getAttribute('formnovalidate')) return;
3148
+
3149
+ window.Parsley._remoteCache = {};
3150
 
3151
  var promise = this.whenValidate({ event: event });
3152
 
3158
  event.stopImmediatePropagation();
3159
  event.preventDefault();
3160
  if ('pending' === promise.state()) promise.done(function () {
3161
+ _this5._submit(submitSource);
3162
  });
3163
  }
3164
  },
3165
 
3166
  onSubmitButton: function onSubmitButton(event) {
3167
+ this._submitSource = event.currentTarget;
3168
  },
3169
  // internal
3170
  // _submit submits the form, this time without going through the validations.
3171
  // Care must be taken to "fake" the actual submit button being clicked.
3172
+ _submit: function _submit(submitSource) {
3173
  if (false === this._trigger('submit')) return;
3174
  // Add submit button's data
3175
+ if (submitSource) {
3176
  var $synthetic = this.$element.find('.parsley-synthetic-submit-button').prop('disabled', false);
3177
  if (0 === $synthetic.length) $synthetic = $('<input class="parsley-synthetic-submit-button" type="hidden">').appendTo(this.$element);
3178
  $synthetic.attr({
3179
+ name: submitSource.getAttribute('name'),
3180
+ value: submitSource.getAttribute('value')
3181
  });
3182
  }
3183
 
3184
+ this.$element.trigger(_extends($.Event('submit'), { parsley: true }));
3185
  },
3186
 
3187
  // Performs validation on fields while triggering events.
3191
  // Consider using `whenValidate` instead.
3192
  validate: function validate(options) {
3193
  if (arguments.length >= 1 && !$.isPlainObject(options)) {
3194
+ Utils.warnOnce('Calling validate on a parsley form without passing arguments as an object is deprecated.');
3195
 
3196
  var _arguments = _slice.call(arguments);
3197
 
3205
  },
3206
 
3207
  whenValidate: function whenValidate() {
3208
+ var _Utils$all$done$fail$always,
3209
  _this6 = this;
3210
 
3211
  var _ref7 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
3216
 
3217
  this.submitEvent = event;
3218
  if (event) {
3219
+ this.submitEvent = _extends({}, event, { preventDefault: function preventDefault() {
3220
+ Utils.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`");
3221
  _this6.validationResult = false;
3222
  } });
3223
  }
3235
  });
3236
  });
3237
 
3238
+ return (_Utils$all$done$fail$always = Utils.all(promises).done(function () {
3239
  _this6._trigger('success');
3240
  }).fail(function () {
3241
  _this6.validationResult = false;
3243
  _this6._trigger('error');
3244
  }).always(function () {
3245
  _this6._trigger('validated');
3246
+ })).pipe.apply(_Utils$all$done$fail$always, _toConsumableArray(this._pipeAccordingToValidationResult()));
3247
  },
3248
 
3249
  // Iterate over refreshed fields, and stop on first failure.
3252
  // Prefer using `whenValid` instead.
3253
  isValid: function isValid(options) {
3254
  if (arguments.length >= 1 && !$.isPlainObject(options)) {
3255
+ Utils.warnOnce('Calling isValid on a parsley form without passing arguments as an object is deprecated.');
3256
 
3257
  var _arguments2 = _slice.call(arguments);
3258
 
3282
  return field.whenValid({ group: group, force: force });
3283
  });
3284
  });
3285
+ return Utils.all(promises);
3286
  },
3287
 
3288
  // Reset UI
3331
  }
3332
  });
3333
 
3334
+ $.each(Utils.difference(oldFields, _this8.fields), function (_, field) {
3335
  field.reset();
3336
  });
3337
  });
3367
  var Constraint = function Constraint(parsleyField, name, requirements, priority, isDomConstraint) {
3368
  var validatorSpec = window.Parsley._validatorRegistry.validators[name];
3369
  var validator = new Validator(validatorSpec);
3370
+ priority = priority || parsleyField.options[name + 'Priority'] || validator.priority;
3371
+ isDomConstraint = true === isDomConstraint;
3372
 
3373
+ _extends(this, {
3374
  validator: validator,
3375
  name: name,
3376
  requirements: requirements,
3377
+ priority: priority,
3378
+ isDomConstraint: isDomConstraint
3379
  });
3380
  this._parseRequirements(parsleyField.options);
3381
  };
3404
  var Field = function Field(field, domOptions, options, parsleyFormInstance) {
3405
  this.__class__ = 'Field';
3406
 
3407
+ this.element = field;
3408
  this.$element = $(field);
3409
 
3410
  // Set parent if we have one
3433
  // `null` if validation is not finished. Prefer using whenValidate
3434
  validate: function validate(options) {
3435
  if (arguments.length >= 1 && !$.isPlainObject(options)) {
3436
+ Utils.warnOnce('Calling validate on a parsley field without passing arguments as an object is deprecated.');
3437
  options = { options: options };
3438
  }
3439
  var promise = this.whenValidate(options);
3497
  },
3498
 
3499
  _isInGroup: function _isInGroup(group) {
3500
+ if (Array.isArray(this.options.group)) return -1 !== $.inArray(group, this.options.group);
3501
  return this.options.group === group;
3502
  },
3503
 
3507
  // See also `whenValid`.
3508
  isValid: function isValid(options) {
3509
  if (arguments.length >= 1 && !$.isPlainObject(options)) {
3510
+ Utils.warnOnce('Calling isValid on a parsley field without passing arguments as an object is deprecated.');
3511
 
3512
  var _arguments3 = _slice.call(arguments);
3513
 
3558
  $.each(groupedConstraints, function (_, constraints) {
3559
  // Process one group of constraints at a time, we validate the constraints
3560
  // and combine the promises together.
3561
+ var promise = Utils.all($.map(constraints, function (constraint) {
3562
  return _this11._validateConstraint(value, constraint);
3563
  }));
3564
  promises.push(promise);
3565
  if (promise.state() === 'rejected') return false; // Interrupt processing if a group has already failed
3566
  });
3567
+ return Utils.all(promises);
3568
  },
3569
 
3570
  // @returns a promise
3575
  // Map false to a failed promise
3576
  if (false === result) result = $.Deferred().reject();
3577
  // Make sure we return a promise and that we record failures
3578
+ return Utils.all([result]).fail(function (errorMessage) {
3579
  if (!(_this12.validationResult instanceof Array)) _this12.validationResult = [];
3580
  _this12.validationResult.push({
3581
  assert: constraint,
3684
  // Bind specific HTML5 constraints to be HTML5 compliant
3685
  _bindHtml5Constraints: function _bindHtml5Constraints() {
3686
  // html5 required
3687
+ if (null !== this.element.getAttribute('required')) this.addConstraint('required', true, undefined, true);
3688
 
3689
  // html5 pattern
3690
+ if (null !== this.element.getAttribute('pattern')) this.addConstraint('pattern', this.element.getAttribute('pattern'), undefined, true);
3691
 
3692
  // range
3693
+ var min = this.element.getAttribute('min');
3694
+ var max = this.element.getAttribute('max');
3695
+ if (null !== min && null !== max) this.addConstraint('range', [min, max], undefined, true);
3696
 
3697
  // HTML5 min
3698
+ else if (null !== min) this.addConstraint('min', min, undefined, true);
3699
 
3700
  // HTML5 max
3701
+ else if (null !== max) this.addConstraint('max', max, undefined, true);
3702
 
3703
  // length
3704
+ if (null !== this.element.getAttribute('minlength') && null !== this.element.getAttribute('maxlength')) this.addConstraint('length', [this.element.getAttribute('minlength'), this.element.getAttribute('maxlength')], undefined, true);
3705
 
3706
  // HTML5 minlength
3707
+ else if (null !== this.element.getAttribute('minlength')) this.addConstraint('minlength', this.element.getAttribute('minlength'), undefined, true);
3708
 
3709
  // HTML5 maxlength
3710
+ else if (null !== this.element.getAttribute('maxlength')) this.addConstraint('maxlength', this.element.getAttribute('maxlength'), undefined, true);
3711
 
3712
  // html5 types
3713
+ var type = this.element.type;
 
 
3714
 
3715
  // Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise
3716
  if ('number' === type) {
3717
  return this.addConstraint('type', ['number', {
3718
+ step: this.element.getAttribute('step') || '1',
3719
+ base: min || this.element.getAttribute('value')
3720
  }], undefined, true);
3721
  // Regular other HTML5 supported types
3722
  } else if (/^(email|url|range|date)$/i.test(type)) {
3744
  // Use `data-parsley-whitespace="squish"` to auto squish input value
3745
  // Use `data-parsley-whitespace="trim"` to auto trim input value
3746
  _handleWhitespace: function _handleWhitespace(value) {
3747
+ if (true === this.options.trimValue) Utils.warnOnce('data-parsley-trim-value="true" is deprecated, please use data-parsley-whitespace="trim"');
3748
 
3749
  if ('squish' === this.options.whitespace) value = value.replace(/\s{2,}/g, ' ');
3750
 
3751
+ if ('trim' === this.options.whitespace || 'squish' === this.options.whitespace || true === this.options.trimValue) value = Utils.trimString(value);
3752
 
3753
  return value;
3754
  },
3804
  this.constraints = [];
3805
 
3806
  // Select multiple special treatment
3807
+ if (this.element.nodeName === 'SELECT') {
3808
  this.actualizeOptions()._bindConstraints();
3809
 
3810
  return this;
3833
  if ('function' === typeof this.options.value) return this.options.value(this);else if ('undefined' !== typeof this.options.value) return this.options.value;
3834
 
3835
  // Radio input case
3836
+ if (this.element.nodeName === 'INPUT') {
3837
+ if (this.element.type === 'radio') return this._findRelated().filter(':checked').val() || '';
3838
 
3839
+ // checkbox input case
3840
+ if (this.element.type === 'checkbox') {
3841
+ var values = [];
3842
 
3843
+ this._findRelated().filter(':checked').each(function () {
3844
+ values.push($(this).val());
3845
+ });
3846
 
3847
+ return values;
3848
+ }
3849
  }
3850
 
3851
  // Select multiple case
3852
+ if (this.element.nodeName === 'SELECT' && null === this.$element.val()) return [];
3853
 
3854
  // Default case that should never happen
3855
  return this.$element.val();
3863
  };
3864
 
3865
  var Factory = function Factory(element, options, parsleyFormInstance) {
3866
+ this.element = element;
3867
  this.$element = $(element);
3868
 
3869
  // If the element has already been bound, returns its saved Parsley instance
3877
  }
3878
 
3879
  if ('object' === typeof options) {
3880
+ _extends(savedparsleyFormInstance.options, options);
3881
  }
3882
 
3883
  return savedparsleyFormInstance;
3895
  Factory.prototype = {
3896
  init: function init(options) {
3897
  this.__class__ = 'Parsley';
3898
+ this.__version__ = '2.7.2';
3899
+ this.__id__ = Utils.generateID();
3900
 
3901
  // Pre-compute options
3902
  this._resetOptions(options);
3903
 
3904
  // A Form instance is obviously a `<form>` element but also every node that is not an input and has the `data-parsley-validate` attribute
3905
+ if (this.element.nodeName === 'FORM' || Utils.checkAttr(this.element, this.options.namespace, 'validate') && !this.$element.is(this.options.inputs)) return this.bind('parsleyForm');
3906
 
3907
  // Every other element is bound as a `Field` or `FieldMultiple`
3908
  return this.isMultiple() ? this.handleMultiple() : this.bind('parsleyField');
3909
  },
3910
 
3911
  isMultiple: function isMultiple() {
3912
+ return this.element.type === 'radio' || this.element.type === 'checkbox' || this.element.nodeName === 'SELECT' && null !== this.element.getAttribute('multiple');
3913
  },
3914
 
3915
  // Multiples fields are a real nightmare :(
3922
  var parsleyMultipleInstance;
3923
 
3924
  // Handle multiple name
3925
+ this.options.multiple = this.options.multiple || (name = this.element.getAttribute('name')) || this.element.getAttribute('id');
 
3926
 
3927
  // Special select multiple input
3928
+ if (this.element.nodeName === 'SELECT' && null !== this.element.getAttribute('multiple')) {
3929
  this.options.multiple = this.options.multiple || this.__id__;
3930
  return this.bind('parsleyFieldMultiple');
3931
 
3932
  // Else for radio / checkboxes, we need a `name` or `data-parsley-multiple` to properly bind it
3933
  } else if (!this.options.multiple) {
3934
+ Utils.warn('To be bound by Parsley, a radio, a checkbox and a multiple select input must have either a name or a multiple option.', this.$element);
3935
  return this;
3936
  }
3937
 
3939
  this.options.multiple = this.options.multiple.replace(/(:|\.|\[|\]|\{|\}|\$)/g, '');
3940
 
3941
  // Add proper `data-parsley-multiple` to siblings if we have a valid multiple name
3942
+ if (name) {
3943
  $('input[name="' + name + '"]').each(function (i, input) {
3944
+ if (input.type === 'radio' || input.type === 'checkbox') input.setAttribute(_this13.options.namespace + 'multiple', _this13.options.multiple);
3945
  });
3946
  }
3947
 
3972
 
3973
  switch (type) {
3974
  case 'parsleyForm':
3975
+ parsleyInstance = $.extend(new Form(this.element, this.domOptions, this.options), new Base(), window.ParsleyExtend)._bindFields();
3976
  break;
3977
  case 'parsleyField':
3978
+ parsleyInstance = $.extend(new parsley_field(this.element, this.domOptions, this.options, this.parent), new Base(), window.ParsleyExtend);
3979
  break;
3980
  case 'parsleyFieldMultiple':
3981
+ parsleyInstance = $.extend(new parsley_field(this.element, this.domOptions, this.options, this.parent), new Multiple(), new Base(), window.ParsleyExtend)._init();
3982
  break;
3983
  default:
3984
  throw new Error(type + 'is not a supported Parsley type');
3985
  }
3986
 
3987
+ if (this.options.multiple) Utils.setAttr(this.element, this.options.namespace, 'multiple', this.options.multiple);
3988
 
3989
  if ('undefined' !== typeof doNotStore) {
3990
  this.$element.data('FieldMultiple', parsleyInstance);
4008
  throw "The loaded version of jQuery is too old. Please upgrade to 1.8.x or better.";
4009
  }
4010
  if (!vernums.forEach) {
4011
+ Utils.warn('Parsley requires ES5 to run properly. Please include https://github.com/es-shims/es5-shim');
4012
  }
4013
  // Inherit `on`, `off` & `trigger` to Parsley:
4014
+ var Parsley = _extends(new Base(), {
4015
+ element: document,
4016
  $element: $(document),
4017
  actualizeOptions: null,
4018
  _resetOptions: null,
4019
  Factory: Factory,
4020
+ version: '2.7.2'
4021
  });
4022
 
4023
  // Supplement Field and Form with Base
4024
  // This way, the constructors will have access to those methods
4025
+ _extends(parsley_field.prototype, UI.Field, Base.prototype);
4026
+ _extends(Form.prototype, UI.Form, Base.prototype);
4027
  // Inherit actualizeOptions and _resetOptions:
4028
+ _extends(Factory.prototype, Base.prototype);
4029
 
4030
  // ### jQuery API
4031
  // `$('.elem').parsley(options)` or `$('.elem').psly(options)`
4042
 
4043
  // Return undefined if applied to non existing DOM element
4044
  if (!$(this).length) {
4045
+ Utils.warn('You must bind Parsley on an existing element.');
4046
 
4047
  return;
4048
  }
4049
 
4050
+ return new Factory(this[0], options);
4051
  };
4052
 
4053
  // ### Field and Form extension
4056
 
4057
  // ### Parsley config
4058
  // Inherit from ParsleyDefault, and copy over any existing values
4059
+ Parsley.options = _extends(Utils.objectCreate(Defaults), window.ParsleyConfig);
4060
  window.ParsleyConfig = Parsley.options; // Old way of accessing global options
4061
 
4062
  // ### Globals
4063
  window.Parsley = window.psly = Parsley;
4064
+ Parsley.Utils = Utils;
4065
  window.ParsleyUtils = {};
4066
+ $.each(Utils, function (key, value) {
4067
  if ('function' === typeof value) {
4068
  window.ParsleyUtils[key] = function () {
4069
+ Utils.warnOnce('Accessing `window.ParsleyUtils` is deprecated. Use `window.Parsley.Utils` instead.');
4070
+ return Utils[key].apply(Utils, arguments);
4071
  };
4072
  }
4073
  });
4076
  var registry = window.Parsley._validatorRegistry = new ValidatorRegistry(window.ParsleyConfig.validators, window.ParsleyConfig.i18n);
4077
  window.ParsleyValidator = {};
4078
  $.each('setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator'.split(' '), function (i, method) {
4079
+ window.Parsley[method] = function () {
4080
+ return registry[method].apply(registry, arguments);
4081
+ };
4082
  window.ParsleyValidator[method] = function () {
4083
  var _window$Parsley;
4084
 
4085
+ Utils.warnOnce('Accessing the method \'' + method + '\' through Validator is deprecated. Simply call \'window.Parsley.' + method + '(...)\'');
4086
  return (_window$Parsley = window.Parsley)[method].apply(_window$Parsley, arguments);
4087
  };
4088
  });
4093
  window.ParsleyUI = {
4094
  removeError: function removeError(instance, name, doNotUpdateClass) {
4095
  var updateClass = true !== doNotUpdateClass;
4096
+ Utils.warnOnce('Accessing UI is deprecated. Call \'removeError\' on the instance directly. Please comment in issue 1073 as to your need to call this method.');
4097
  return instance.removeError(name, { updateClass: updateClass });
4098
  },
4099
  getErrorsMessages: function getErrorsMessages(instance) {
4100
+ Utils.warnOnce('Accessing UI is deprecated. Call \'getErrorsMessages\' on the instance directly.');
4101
  return instance.getErrorsMessages();
4102
  }
4103
  };
4104
  $.each('addError updateError'.split(' '), function (i, method) {
4105
  window.ParsleyUI[method] = function (instance, name, message, assert, doNotUpdateClass) {
4106
  var updateClass = true !== doNotUpdateClass;
4107
+ Utils.warnOnce('Accessing UI is deprecated. Call \'' + method + '\' on the instance directly. Please comment in issue 1073 as to your need to call this method.');
4108
  return instance[method](name, { message: message, assert: assert, updateClass: updateClass });
4109
  };
4110
  });
4120
 
4121
  var o = $({});
4122
  var deprecated = function deprecated() {
4123
+ Utils.warnOnce("Parsley's pubsub module is deprecated; use the 'on' and 'off' methods on parsley instances or window.Parsley");
4124
  };
4125
 
4126
  // Returns an event handler that calls `fn` with the arguments it expects
4260
  if (url.indexOf('{value}') > -1) {
4261
  url = url.replace('{value}', encodeURIComponent(value));
4262
  } else {
4263
+ data[instance.element.getAttribute('name') || instance.element.getAttribute('id')] = value;
4264
  }
4265
 
4266
  // Merge options passed in from the function with the ones in the attribute
4301
  Parsley._remoteCache = {};
4302
  });
4303
 
4304
+ Base.prototype.addAsyncValidator = function () {
4305
  Utils.warnOnce('Accessing the method `addAsyncValidator` through an instance is deprecated. Simply call `Parsley.addAsyncValidator(...)`');
4306
  return Parsley.addAsyncValidator.apply(Parsley, arguments);
4307
  };
4350
 
4351
  // Slightly odd way construct our object. This way methods are force bound.
4352
  // Used to test for duplicate library.
4353
+ _extends(this, {
4354
 
4355
  // For browsers that do not support isTrusted, assumes event is native.
4356
  isNativeEvent: function isNativeEvent(evt) {
lang/index.php CHANGED
@@ -1,3 +0,0 @@
1
- <?php
2
-
3
- // Silence is golden
 
 
 
lang/mailpoet-de_DE.mo CHANGED
Binary file
lang/mailpoet-de_DE.po CHANGED
@@ -10,8 +10,8 @@ msgstr ""
10
  "Project-Id-Version: MP3\n"
11
  "Report-Msgid-Bugs-To: http://support.mailpoet.com/\n"
12
  "POT-Creation-Date: 2017-04-25 15:49:50+00:00\n"
13
- "PO-Revision-Date: 2017-05-01 11:15+0000\n"
14
- "Last-Translator: Birgit Olzem <coachbirgit@gmail.com>\n"
15
  "Language-Team: German (Germany) (http://www.transifex.com/wysija/mp3/language/de_DE/)\n"
16
  "MIME-Version: 1.0\n"
17
  "Content-Type: text/plain; charset=UTF-8\n"
@@ -3402,7 +3402,7 @@ msgstr "Täglich um %$1s senden"
3402
 
3403
  #: views/newsletters.html:229
3404
  msgid "Send weekly on %$1s at %$2s"
3405
- msgstr "Wöchentlich am %1$s um %$2s senden"
3406
 
3407
  #: views/newsletters.html:230
3408
  msgid "Send monthly on the %$1s at %$2s"
10
  "Project-Id-Version: MP3\n"
11
  "Report-Msgid-Bugs-To: http://support.mailpoet.com/\n"
12
  "POT-Creation-Date: 2017-04-25 15:49:50+00:00\n"
13
+ "PO-Revision-Date: 2017-05-19 15:11+0000\n"
14
+ "Last-Translator: Kim Gjerstad <staff@mailpoet.com>\n"
15
  "Language-Team: German (Germany) (http://www.transifex.com/wysija/mp3/language/de_DE/)\n"
16
  "MIME-Version: 1.0\n"
17
  "Content-Type: text/plain; charset=UTF-8\n"
3402
 
3403
  #: views/newsletters.html:229
3404
  msgid "Send weekly on %$1s at %$2s"
3405
+ msgstr "Wöchentlich am %$1s um %$2s senden"
3406
 
3407
  #: views/newsletters.html:230
3408
  msgid "Send monthly on the %$1s at %$2s"
lang/mailpoet-pt_PT.mo CHANGED
Binary file
lang/mailpoet-pt_PT.po CHANGED
@@ -9,8 +9,8 @@ msgstr ""
9
  "Project-Id-Version: MP3\n"
10
  "Report-Msgid-Bugs-To: http://support.mailpoet.com/\n"
11
  "POT-Creation-Date: 2017-04-25 15:49:50+00:00\n"
12
- "PO-Revision-Date: 2017-04-26 00:20+0000\n"
13
- "Last-Translator: Pedro Mendonça <ped.gaspar@gmail.com>\n"
14
  "Language-Team: Portuguese (Portugal) (http://www.transifex.com/wysija/mp3/language/pt_PT/)\n"
15
  "MIME-Version: 1.0\n"
16
  "Content-Type: text/plain; charset=UTF-8\n"
9
  "Project-Id-Version: MP3\n"
10
  "Report-Msgid-Bugs-To: http://support.mailpoet.com/\n"
11
  "POT-Creation-Date: 2017-04-25 15:49:50+00:00\n"
12
+ "PO-Revision-Date: 2017-05-23 09:37+0000\n"
13
+ "Last-Translator: Álvaro Góis dos Santos <alvarogois@ovni.org>\n"
14
  "Language-Team: Portuguese (Portugal) (http://www.transifex.com/wysija/mp3/language/pt_PT/)\n"
15
  "MIME-Version: 1.0\n"
16
  "Content-Type: text/plain; charset=UTF-8\n"
lang/mailpoet.pot CHANGED
@@ -4,7 +4,7 @@ msgid ""
4
  msgstr ""
5
  "Project-Id-Version: \n"
6
  "Report-Msgid-Bugs-To: http://support.mailpoet.com/\n"
7
- "POT-Creation-Date: 2017-05-16 14:14:17+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -26,177 +26,200 @@ msgstr ""
26
  "X-Poedit-Bookmarks: \n"
27
  "X-Textdomain-Support: yes\n"
28
 
29
- #: lib/API/API.php:59 lib/API/API.php:86
 
 
 
 
30
  msgid "Invalid API request."
31
  msgstr ""
32
 
33
- #: lib/API/API.php:126
34
  msgid "Invalid API endpoint."
35
  msgstr ""
36
 
37
- #: lib/API/API.php:138
38
  msgid "You do not have the required permissions."
39
  msgstr ""
40
 
41
- #: lib/API/Endpoint.php:21
42
  msgid "An unknown error occurred."
43
  msgstr ""
44
 
45
- #: lib/API/Endpoint.php:30
46
  msgid "Invalid request parameters"
47
  msgstr ""
48
 
49
- #: lib/API/Endpoints/v1/CustomFields.php:24
50
- #: lib/API/Endpoints/v1/CustomFields.php:51
51
  msgid "This custom field does not exist."
52
  msgstr ""
53
 
54
- #: lib/API/Endpoints/v1/Forms.php:20 lib/API/Endpoints/v1/Forms.php:127
55
- #: lib/API/Endpoints/v1/Forms.php:209 lib/API/Endpoints/v1/Forms.php:225
56
- #: lib/API/Endpoints/v1/Forms.php:241 lib/API/Endpoints/v1/Forms.php:255
57
  msgid "This form does not exist."
58
  msgstr ""
59
 
60
- #: lib/API/Endpoints/v1/Forms.php:60 lib/API/Endpoints/v1/Forms.php:139
61
  msgid "New form"
62
  msgstr ""
63
 
64
- #: lib/API/Endpoints/v1/Forms.php:64 lib/API/Endpoints/v1/Forms.php:68
 
65
  #: lib/Subscribers/ImportExport/ImportExportFactory.php:32
66
  #: views/newsletter/editor.html:928 views/newsletter/editor.html:929
67
  msgid "Email"
68
  msgstr ""
69
 
70
- #: lib/API/Endpoints/v1/Forms.php:74
71
  msgid "Submit"
72
  msgstr ""
73
 
74
- #: lib/API/Endpoints/v1/Forms.php:78
75
  msgid "Subscribe!"
76
  msgstr ""
77
 
78
- #: lib/API/Endpoints/v1/Forms.php:84
79
  msgid "Check your inbox or spam folder to confirm your subscription."
80
  msgstr ""
81
 
82
- #: lib/API/Endpoints/v1/Forms.php:259 lib/API/Endpoints/v1/Newsletters.php:204
83
- #: lib/API/Endpoints/v1/Segments.php:119
84
  msgid "Copy of %s"
85
  msgstr ""
86
 
87
- #: lib/API/Endpoints/v1/Mailer.php:29 lib/API/Endpoints/v1/Newsletters.php:303
88
  msgid "The email could not be sent: %s"
89
  msgstr ""
90
 
91
- #: lib/API/Endpoints/v1/NewsletterTemplates.php:16
92
- #: lib/API/Endpoints/v1/NewsletterTemplates.php:52
93
  msgid "This template does not exist."
94
  msgstr ""
95
 
96
- #: lib/API/Endpoints/v1/Newsletters.php:30
97
- #: lib/API/Endpoints/v1/Newsletters.php:133
98
- #: lib/API/Endpoints/v1/Newsletters.php:154
99
- #: lib/API/Endpoints/v1/Newsletters.php:170
100
- #: lib/API/Endpoints/v1/Newsletters.php:186
101
- #: lib/API/Endpoints/v1/Newsletters.php:200
102
- #: lib/API/Endpoints/v1/Newsletters.php:233
103
- #: lib/API/Endpoints/v1/Newsletters.php:264
104
- #: lib/API/Endpoints/v1/SendingQueue.php:28
105
- #: lib/API/Endpoints/v1/SendingQueue.php:115
106
- #: lib/API/Endpoints/v1/SendingQueue.php:141
107
  msgid "This newsletter does not exist."
108
  msgstr ""
109
 
110
- #: lib/API/Endpoints/v1/Newsletters.php:124
111
  msgid "You need to specify a status."
112
  msgstr ""
113
 
114
- #: lib/API/Endpoints/v1/Newsletters.php:224
115
  msgid "Newsletter data is missing."
116
  msgstr ""
117
 
118
- #: lib/API/Endpoints/v1/Newsletters.php:255
119
  msgid "Please specify receiver information."
120
  msgstr ""
121
 
122
- #: lib/API/Endpoints/v1/Segments.php:18 lib/API/Endpoints/v1/Segments.php:69
123
- #: lib/API/Endpoints/v1/Segments.php:85 lib/API/Endpoints/v1/Segments.php:101
124
- #: lib/API/Endpoints/v1/Segments.php:115
125
  msgid "This list does not exist."
126
  msgstr ""
127
 
128
- #: lib/API/Endpoints/v1/SendingQueue.php:48
129
  msgid "This newsletter is already being sent."
130
  msgstr ""
131
 
132
- #: lib/API/Endpoints/v1/SendingQueue.php:79
133
  msgid "There are no subscribers in that list!"
134
  msgstr ""
135
 
136
- #: lib/API/Endpoints/v1/SendingQueue.php:122
137
- #: lib/API/Endpoints/v1/SendingQueue.php:148
138
  msgid "This newsletter has not been sent yet."
139
  msgstr ""
140
 
141
- #: lib/API/Endpoints/v1/Services.php:26 lib/API/Endpoints/v1/Services.php:75
142
  msgid "Please specify a key."
143
  msgstr ""
144
 
145
- #: lib/API/Endpoints/v1/Services.php:42
146
  msgid "Your MailPoet API key is valid!"
147
  msgstr ""
148
 
149
- #: lib/API/Endpoints/v1/Services.php:45
150
  msgid "Your MailPoet key expires on %s!"
151
  msgstr ""
152
 
153
- #: lib/API/Endpoints/v1/Services.php:56
154
  msgid "Your MailPoet key is invalid!"
155
  msgstr ""
156
 
157
- #: lib/API/Endpoints/v1/Services.php:61
158
  msgid "Error validating API key, please try again later (code: %s)"
159
  msgstr ""
160
 
161
- #: lib/API/Endpoints/v1/Services.php:91 views/settings/premium.html:33
162
  msgid "Your license key has been successfully validated."
163
  msgstr ""
164
 
165
- #: lib/API/Endpoints/v1/Services.php:94
166
  msgid "Your license key expires on %s."
167
  msgstr ""
168
 
169
- #: lib/API/Endpoints/v1/Services.php:109 views/settings/premium.html:41
170
  msgid "Your license key is invalid."
171
  msgstr ""
172
 
173
- #: lib/API/Endpoints/v1/Services.php:112
174
  msgid "Your license key is already used on another site."
175
  msgstr ""
176
 
177
- #: lib/API/Endpoints/v1/Services.php:117
178
  msgid "Error validating license key, please try again later (code: %s)"
179
  msgstr ""
180
 
181
- #: lib/API/Endpoints/v1/Settings.php:20
182
  msgid "You have not specified any settings to be saved."
183
  msgstr ""
184
 
185
- #: lib/API/Endpoints/v1/Subscribers.php:25
186
- #: lib/API/Endpoints/v1/Subscribers.php:139
187
- #: lib/API/Endpoints/v1/Subscribers.php:155
188
- #: lib/API/Endpoints/v1/Subscribers.php:171
189
  msgid "This subscriber does not exist."
190
  msgstr ""
191
 
192
- #: lib/API/Endpoints/v1/Subscribers.php:66
193
  msgid "Please specify a valid form ID."
194
  msgstr ""
195
 
196
- #: lib/API/Endpoints/v1/Subscribers.php:79 views/form/editor.html:57
197
  msgid "Please select a list."
198
  msgstr ""
199
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  #: lib/Config/Hooks.php:149
201
  msgid "MailPoet Newsletter"
202
  msgstr ""
@@ -1259,26 +1282,26 @@ msgstr ""
1259
  msgid "MailPoet API key is invalid!"
1260
  msgstr ""
1261
 
1262
- #: lib/Models/CustomField.php:14 lib/Models/Form.php:13
1263
  #: lib/Models/NewsletterOptionField.php:12 lib/Models/NewsletterTemplate.php:13
1264
- #: lib/Models/Segment.php:13 lib/Models/Setting.php:22
1265
  #: views/form/templates/settings/field_form.hbs:53
1266
  #: views/subscribers/importExport/import/step2.html:137
1267
  msgid "Please specify a name."
1268
  msgstr ""
1269
 
1270
- #: lib/Models/CustomField.php:17 lib/Models/Newsletter.php:26
1271
  #: views/form/templates/settings/field_form.hbs:16
1272
  msgid "Please specify a type."
1273
  msgstr ""
1274
 
1275
  #: lib/Models/Form.php:93 lib/Models/Newsletter.php:543
1276
- #: lib/Models/Segment.php:131 lib/Models/Subscriber.php:345
1277
  msgid "All"
1278
  msgstr ""
1279
 
1280
  #: lib/Models/Form.php:98 lib/Models/Newsletter.php:613
1281
- #: lib/Models/Segment.php:136 lib/Models/Subscriber.php:370 views/forms.html:57
1282
  #: views/newsletters.html:76 views/segments.html:50
1283
  #: views/subscribers/subscribers.html:34
1284
  msgid "Trash"
@@ -1331,15 +1354,15 @@ msgstr ""
1331
  msgid "The template body cannot be empty."
1332
  msgstr ""
1333
 
1334
- #: lib/Models/Segment.php:112 views/subscribers/subscribers.html:83
1335
  msgid "WordPress Users"
1336
  msgstr ""
1337
 
1338
- #: lib/Models/Segment.php:114
1339
  msgid "This list contains all of your WordPress users."
1340
  msgstr ""
1341
 
1342
- #: lib/Models/Segment.php:198
1343
  msgid "Not in a List"
1344
  msgstr ""
1345
 
@@ -1575,18 +1598,6 @@ msgstr ""
1575
  msgid "Not In List"
1576
  msgstr ""
1577
 
1578
- #: lib/Subscribers/ImportExport/ImportExportFactory.php:33
1579
- #: lib/Subscription/Pages.php:266 views/form/editor.html:225
1580
- #: views/form/editor.html:228 views/subscribers/subscribers.html:49
1581
- msgid "First name"
1582
- msgstr ""
1583
-
1584
- #: lib/Subscribers/ImportExport/ImportExportFactory.php:34
1585
- #: lib/Subscription/Pages.php:275 views/form/editor.html:234
1586
- #: views/form/editor.html:237 views/subscribers/subscribers.html:50
1587
- msgid "Last name"
1588
- msgstr ""
1589
-
1590
  #: lib/Subscribers/ImportExport/ImportExportFactory.php:35
1591
  #: lib/Subscription/Pages.php:285 views/newsletters.html:62
1592
  #: views/subscribers/subscribers.html:51 views/subscribers/subscribers.html:62
4
  msgstr ""
5
  "Project-Id-Version: \n"
6
  "Report-Msgid-Bugs-To: http://support.mailpoet.com/\n"
7
+ "POT-Creation-Date: 2017-05-23 10:22:18+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
26
  "X-Poedit-Bookmarks: \n"
27
  "X-Textdomain-Support: yes\n"
28
 
29
+ #: lib/API/API.php:16
30
+ msgid "Invalid API version."
31
+ msgstr ""
32
+
33
+ #: lib/API/JSON/API.php:58 lib/API/JSON/API.php:85
34
  msgid "Invalid API request."
35
  msgstr ""
36
 
37
+ #: lib/API/JSON/API.php:126
38
  msgid "Invalid API endpoint."
39
  msgstr ""
40
 
41
+ #: lib/API/JSON/API.php:138
42
  msgid "You do not have the required permissions."
43
  msgstr ""
44
 
45
+ #: lib/API/JSON/Endpoint.php:21
46
  msgid "An unknown error occurred."
47
  msgstr ""
48
 
49
+ #: lib/API/JSON/Endpoint.php:30
50
  msgid "Invalid request parameters"
51
  msgstr ""
52
 
53
+ #: lib/API/JSON/v1/CustomFields.php:24 lib/API/JSON/v1/CustomFields.php:51
 
54
  msgid "This custom field does not exist."
55
  msgstr ""
56
 
57
+ #: lib/API/JSON/v1/Forms.php:20 lib/API/JSON/v1/Forms.php:127
58
+ #: lib/API/JSON/v1/Forms.php:209 lib/API/JSON/v1/Forms.php:225
59
+ #: lib/API/JSON/v1/Forms.php:241 lib/API/JSON/v1/Forms.php:255
60
  msgid "This form does not exist."
61
  msgstr ""
62
 
63
+ #: lib/API/JSON/v1/Forms.php:60 lib/API/JSON/v1/Forms.php:139
64
  msgid "New form"
65
  msgstr ""
66
 
67
+ #: lib/API/JSON/v1/Forms.php:64 lib/API/JSON/v1/Forms.php:68
68
+ #: lib/API/MP/v1/API.php:17
69
  #: lib/Subscribers/ImportExport/ImportExportFactory.php:32
70
  #: views/newsletter/editor.html:928 views/newsletter/editor.html:929
71
  msgid "Email"
72
  msgstr ""
73
 
74
+ #: lib/API/JSON/v1/Forms.php:74
75
  msgid "Submit"
76
  msgstr ""
77
 
78
+ #: lib/API/JSON/v1/Forms.php:78
79
  msgid "Subscribe!"
80
  msgstr ""
81
 
82
+ #: lib/API/JSON/v1/Forms.php:84
83
  msgid "Check your inbox or spam folder to confirm your subscription."
84
  msgstr ""
85
 
86
+ #: lib/API/JSON/v1/Forms.php:259 lib/API/JSON/v1/Newsletters.php:204
87
+ #: lib/API/JSON/v1/Segments.php:119
88
  msgid "Copy of %s"
89
  msgstr ""
90
 
91
+ #: lib/API/JSON/v1/Mailer.php:29 lib/API/JSON/v1/Newsletters.php:303
92
  msgid "The email could not be sent: %s"
93
  msgstr ""
94
 
95
+ #: lib/API/JSON/v1/NewsletterTemplates.php:16
96
+ #: lib/API/JSON/v1/NewsletterTemplates.php:52
97
  msgid "This template does not exist."
98
  msgstr ""
99
 
100
+ #: lib/API/JSON/v1/Newsletters.php:30 lib/API/JSON/v1/Newsletters.php:133
101
+ #: lib/API/JSON/v1/Newsletters.php:154 lib/API/JSON/v1/Newsletters.php:170
102
+ #: lib/API/JSON/v1/Newsletters.php:186 lib/API/JSON/v1/Newsletters.php:200
103
+ #: lib/API/JSON/v1/Newsletters.php:233 lib/API/JSON/v1/Newsletters.php:264
104
+ #: lib/API/JSON/v1/SendingQueue.php:28 lib/API/JSON/v1/SendingQueue.php:115
105
+ #: lib/API/JSON/v1/SendingQueue.php:141
 
 
 
 
 
106
  msgid "This newsletter does not exist."
107
  msgstr ""
108
 
109
+ #: lib/API/JSON/v1/Newsletters.php:124
110
  msgid "You need to specify a status."
111
  msgstr ""
112
 
113
+ #: lib/API/JSON/v1/Newsletters.php:224
114
  msgid "Newsletter data is missing."
115
  msgstr ""
116
 
117
+ #: lib/API/JSON/v1/Newsletters.php:255
118
  msgid "Please specify receiver information."
119
  msgstr ""
120
 
121
+ #: lib/API/JSON/v1/Segments.php:18 lib/API/JSON/v1/Segments.php:69
122
+ #: lib/API/JSON/v1/Segments.php:85 lib/API/JSON/v1/Segments.php:101
123
+ #: lib/API/JSON/v1/Segments.php:115
124
  msgid "This list does not exist."
125
  msgstr ""
126
 
127
+ #: lib/API/JSON/v1/SendingQueue.php:48
128
  msgid "This newsletter is already being sent."
129
  msgstr ""
130
 
131
+ #: lib/API/JSON/v1/SendingQueue.php:79
132
  msgid "There are no subscribers in that list!"
133
  msgstr ""
134
 
135
+ #: lib/API/JSON/v1/SendingQueue.php:122 lib/API/JSON/v1/SendingQueue.php:148
 
136
  msgid "This newsletter has not been sent yet."
137
  msgstr ""
138
 
139
+ #: lib/API/JSON/v1/Services.php:26 lib/API/JSON/v1/Services.php:75
140
  msgid "Please specify a key."
141
  msgstr ""
142
 
143
+ #: lib/API/JSON/v1/Services.php:42
144
  msgid "Your MailPoet API key is valid!"
145
  msgstr ""
146
 
147
+ #: lib/API/JSON/v1/Services.php:45
148
  msgid "Your MailPoet key expires on %s!"
149
  msgstr ""
150
 
151
+ #: lib/API/JSON/v1/Services.php:56
152
  msgid "Your MailPoet key is invalid!"
153
  msgstr ""
154
 
155
+ #: lib/API/JSON/v1/Services.php:61
156
  msgid "Error validating API key, please try again later (code: %s)"
157
  msgstr ""
158
 
159
+ #: lib/API/JSON/v1/Services.php:91 views/settings/premium.html:33
160
  msgid "Your license key has been successfully validated."
161
  msgstr ""
162
 
163
+ #: lib/API/JSON/v1/Services.php:94
164
  msgid "Your license key expires on %s."
165
  msgstr ""
166
 
167
+ #: lib/API/JSON/v1/Services.php:109 views/settings/premium.html:41
168
  msgid "Your license key is invalid."
169
  msgstr ""
170
 
171
+ #: lib/API/JSON/v1/Services.php:112
172
  msgid "Your license key is already used on another site."
173
  msgstr ""
174
 
175
+ #: lib/API/JSON/v1/Services.php:117
176
  msgid "Error validating license key, please try again later (code: %s)"
177
  msgstr ""
178
 
179
+ #: lib/API/JSON/v1/Settings.php:20
180
  msgid "You have not specified any settings to be saved."
181
  msgstr ""
182
 
183
+ #: lib/API/JSON/v1/Subscribers.php:25 lib/API/JSON/v1/Subscribers.php:139
184
+ #: lib/API/JSON/v1/Subscribers.php:155 lib/API/JSON/v1/Subscribers.php:171
185
+ #: lib/API/MP/v1/API.php:48
 
186
  msgid "This subscriber does not exist."
187
  msgstr ""
188
 
189
+ #: lib/API/JSON/v1/Subscribers.php:66
190
  msgid "Please specify a valid form ID."
191
  msgstr ""
192
 
193
+ #: lib/API/JSON/v1/Subscribers.php:79 views/form/editor.html:57
194
  msgid "Please select a list."
195
  msgstr ""
196
 
197
+ #: lib/API/MP/v1/API.php:21
198
+ #: lib/Subscribers/ImportExport/ImportExportFactory.php:33
199
+ #: lib/Subscription/Pages.php:266 views/form/editor.html:225
200
+ #: views/form/editor.html:228 views/subscribers/subscribers.html:49
201
+ msgid "First name"
202
+ msgstr ""
203
+
204
+ #: lib/API/MP/v1/API.php:25
205
+ #: lib/Subscribers/ImportExport/ImportExportFactory.php:34
206
+ #: lib/Subscription/Pages.php:275 views/form/editor.html:234
207
+ #: views/form/editor.html:237 views/subscribers/subscribers.html:50
208
+ msgid "Last name"
209
+ msgstr ""
210
+
211
+ #: lib/API/MP/v1/API.php:54
212
+ msgid "These lists do not exist."
213
+ msgstr ""
214
+
215
+ #: lib/API/MP/v1/API.php:87
216
+ msgid "Subscriber email address is required."
217
+ msgstr ""
218
+
219
+ #: lib/API/MP/v1/API.php:94
220
+ msgid "This subscriber already exists."
221
+ msgstr ""
222
+
223
  #: lib/Config/Hooks.php:149
224
  msgid "MailPoet Newsletter"
225
  msgstr ""
1282
  msgid "MailPoet API key is invalid!"
1283
  msgstr ""
1284
 
1285
+ #: lib/Models/CustomField.php:20 lib/Models/Form.php:13
1286
  #: lib/Models/NewsletterOptionField.php:12 lib/Models/NewsletterTemplate.php:13
1287
+ #: lib/Models/Segment.php:15 lib/Models/Setting.php:22
1288
  #: views/form/templates/settings/field_form.hbs:53
1289
  #: views/subscribers/importExport/import/step2.html:137
1290
  msgid "Please specify a name."
1291
  msgstr ""
1292
 
1293
+ #: lib/Models/CustomField.php:23 lib/Models/Newsletter.php:26
1294
  #: views/form/templates/settings/field_form.hbs:16
1295
  msgid "Please specify a type."
1296
  msgstr ""
1297
 
1298
  #: lib/Models/Form.php:93 lib/Models/Newsletter.php:543
1299
+ #: lib/Models/Segment.php:133 lib/Models/Subscriber.php:345
1300
  msgid "All"
1301
  msgstr ""
1302
 
1303
  #: lib/Models/Form.php:98 lib/Models/Newsletter.php:613
1304
+ #: lib/Models/Segment.php:138 lib/Models/Subscriber.php:370 views/forms.html:57
1305
  #: views/newsletters.html:76 views/segments.html:50
1306
  #: views/subscribers/subscribers.html:34
1307
  msgid "Trash"
1354
  msgid "The template body cannot be empty."
1355
  msgstr ""
1356
 
1357
+ #: lib/Models/Segment.php:114 views/subscribers/subscribers.html:83
1358
  msgid "WordPress Users"
1359
  msgstr ""
1360
 
1361
+ #: lib/Models/Segment.php:116
1362
  msgid "This list contains all of your WordPress users."
1363
  msgstr ""
1364
 
1365
+ #: lib/Models/Segment.php:200
1366
  msgid "Not in a List"
1367
  msgstr ""
1368
 
1598
  msgid "Not In List"
1599
  msgstr ""
1600
 
 
 
 
 
 
 
 
 
 
 
 
 
1601
  #: lib/Subscribers/ImportExport/ImportExportFactory.php:35
1602
  #: lib/Subscription/Pages.php:285 views/newsletters.html:62
1603
  #: views/subscribers/subscribers.html:51 views/subscribers/subscribers.html:62
lib/API/API.php CHANGED
@@ -1,200 +1,18 @@
1
  <?php
2
  namespace MailPoet\API;
3
 
4
- use MailPoet\Config\Env;
5
- use MailPoet\Util\Helpers;
6
- use MailPoet\Util\Security;
7
- use MailPoet\WP\Hooks;
8
-
9
  if(!defined('ABSPATH')) exit;
10
 
11
  class API {
12
- private $_request_api_version;
13
- private $_request_endpoint;
14
- private $_request_method;
15
- private $_request_token;
16
- private $_request_endpoint_class;
17
- private $_request_data = array();
18
- private $_endpoint_namespaces = array();
19
- private $_available_api_versions = array(
20
- 'v1'
21
- );
22
- const CURRENT_VERSION = 'v1';
23
- const ENDPOINTS_LOCATION = 'Endpoints';
24
-
25
- function __construct() {
26
- foreach($this->_available_api_versions as $available_api_version) {
27
- $this->addEndpointNamespace(
28
- sprintf('%s\%s\%s', __NAMESPACE__, self::ENDPOINTS_LOCATION, $available_api_version),
29
- $available_api_version
30
- );
31
- }
32
- }
33
-
34
- function init() {
35
- // admin security token and API version
36
- add_action(
37
- 'admin_head',
38
- array($this, 'setTokenAndAPIVersion')
39
- );
40
-
41
- // ajax (logged in users)
42
- add_action(
43
- 'wp_ajax_mailpoet',
44
- array($this, 'setupAjax')
45
- );
46
-
47
- // ajax (logged out users)
48
- add_action(
49
- 'wp_ajax_nopriv_mailpoet',
50
- array($this, 'setupAjax')
51
- );
52
- }
53
-
54
- function setupAjax() {
55
- Hooks::doAction('mailpoet_api_setup', array($this));
56
- $this->setRequestData($_POST);
57
-
58
- if($this->checkToken() === false) {
59
- $error_message = __('Invalid API request.', 'mailpoet');
60
- $error_response = $this->createErrorResponse(Error::UNAUTHORIZED, $error_message, Response::STATUS_UNAUTHORIZED);
61
- return $error_response->send();
62
- }
63
-
64
- $response = $this->processRoute();
65
- $response->send();
66
  }
67
 
68
- function setRequestData($data) {
69
- $this->_request_api_version = !empty($data['api_version']) ? $data['api_version']: false;
70
-
71
- $this->_request_endpoint = isset($data['endpoint'])
72
- ? Helpers::underscoreToCamelCase(trim($data['endpoint']))
73
- : null;
74
-
75
- // JS part of /wp-admin/customize.php does not like a 'method' field in a form widget
76
- $method_param_name = isset($data['mailpoet_method']) ? 'mailpoet_method' : 'method';
77
- $this->_request_method = isset($data[$method_param_name])
78
- ? Helpers::underscoreToCamelCase(trim($data[$method_param_name]))
79
- : null;
80
-
81
- $this->_request_token = isset($data['token'])
82
- ? trim($data['token'])
83
- : null;
84
-
85
- if(!$this->_request_endpoint || !$this->_request_method || !$this->_request_api_version) {
86
- $error_message = __('Invalid API request.', 'mailpoet');
87
- $error_response = $this->createErrorResponse(Error::BAD_REQUEST, $error_message, Response::STATUS_BAD_REQUEST);
88
- return $error_response;
89
- } else if(!empty($this->_endpoint_namespaces[$this->_request_api_version])) {
90
- foreach($this->_endpoint_namespaces[$this->_request_api_version] as $namespace) {
91
- $endpoint_class = sprintf(
92
- '%s\%s',
93
- $namespace,
94
- ucfirst($this->_request_endpoint)
95
- );
96
- if(class_exists($endpoint_class)) {
97
- $this->_request_endpoint_class = $endpoint_class;
98
- }
99
- }
100
- $this->_request_data = isset($data['data'])
101
- ? stripslashes_deep($data['data'])
102
- : array();
103
-
104
- // remove reserved keywords from data
105
- if(is_array($this->_request_data) && !empty($this->_request_data)) {
106
- // filter out reserved keywords from data
107
- $reserved_keywords = array(
108
- 'token',
109
- 'endpoint',
110
- 'method',
111
- 'api_version',
112
- 'mailpoet_method', // alias of 'method'
113
- 'mailpoet_redirect'
114
- );
115
- $this->_request_data = array_diff_key(
116
- $this->_request_data,
117
- array_flip($reserved_keywords)
118
- );
119
- }
120
  }
121
- }
122
-
123
- function processRoute() {
124
- try {
125
- if(empty($this->_request_endpoint_class)) {
126
- throw new \Exception(__('Invalid API endpoint.', 'mailpoet'));
127
- }
128
-
129
- $endpoint = new $this->_request_endpoint_class();
130
-
131
- // check the accessibility of the requested endpoint's action
132
- // by default, an endpoint's action is considered "private"
133
- $permissions = $endpoint->permissions;
134
- if(array_key_exists($this->_request_method, $permissions) === false ||
135
- $permissions[$this->_request_method] !== Access::ALL
136
- ) {
137
- if($this->checkPermissions() === false) {
138
- $error_message = __('You do not have the required permissions.', 'mailpoet');
139
- $error_response = $this->createErrorResponse(Error::FORBIDDEN, $error_message, Response::STATUS_FORBIDDEN);
140
- return $error_response;
141
- }
142
- }
143
-
144
- $response = $endpoint->{$this->_request_method}($this->_request_data);
145
- return $response;
146
- } catch(\Exception $e) {
147
- $error_message = $e->getMessage();
148
- $error_response = $this->createErrorResponse(Error::BAD_REQUEST, $error_message, Response::STATUS_BAD_REQUEST);
149
- return $error_response;
150
- }
151
- }
152
-
153
- function checkPermissions() {
154
- return current_user_can(Env::$required_permission);
155
- }
156
-
157
- function checkToken() {
158
- return wp_verify_nonce($this->_request_token, 'mailpoet_token');
159
- }
160
-
161
- function setTokenAndAPIVersion() {
162
- $global = '<script type="text/javascript">';
163
- $global .= 'var mailpoet_token = "%s";';
164
- $global .= 'var mailpoet_api_version = "%s";';
165
- $global .= '</script>';
166
- echo sprintf(
167
- $global,
168
- Security::generateToken(),
169
- self::CURRENT_VERSION
170
- );
171
- }
172
-
173
- function addEndpointNamespace($namespace, $version) {
174
- if(!empty($this->_endpoint_namespaces[$version][$namespace])) return;
175
- $this->_endpoint_namespaces[$version][] = $namespace;
176
- }
177
-
178
- function getEndpointNamespaces() {
179
- return $this->_endpoint_namespaces;
180
- }
181
-
182
- function getRequestedEndpointClass() {
183
- return $this->_request_endpoint_class;
184
- }
185
-
186
- function getRequestedAPIVersion() {
187
- return $this->_request_api_version;
188
- }
189
-
190
- function createErrorResponse($error_type, $error_message, $response_status) {
191
- $error_response = new ErrorResponse(
192
- array(
193
- $error_type => $error_message
194
- ),
195
- array(),
196
- $response_status
197
- );
198
- return $error_response;
199
  }
200
  }
1
  <?php
2
  namespace MailPoet\API;
3
 
 
 
 
 
 
4
  if(!defined('ABSPATH')) exit;
5
 
6
  class API {
7
+ static function JSON() {
8
+ return new \MailPoet\API\JSON\API();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  }
10
 
11
+ static function MP($version) {
12
+ $api_class = sprintf('%s\MP\%s\API', __NAMESPACE__, $version);
13
+ if(class_exists($api_class)) {
14
+ return new $api_class();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  }
16
+ throw new \Exception(__('Invalid API version.', 'mailpoet'));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  }
18
  }
lib/API/JSON/API.php ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace MailPoet\API\JSON;
3
+
4
+ use MailPoet\Config\Env;
5
+ use MailPoet\Util\Helpers;
6
+ use MailPoet\Util\Security;
7
+ use MailPoet\WP\Hooks;
8
+
9
+ if(!defined('ABSPATH')) exit;
10
+
11
+ class API {
12
+ private $_request_api_version;
13
+ private $_request_endpoint;
14
+ private $_request_method;
15
+ private $_request_token;
16
+ private $_request_endpoint_class;
17
+ private $_request_data = array();
18
+ private $_endpoint_namespaces = array();
19
+ private $_available_api_versions = array(
20
+ 'v1'
21
+ );
22
+ const CURRENT_VERSION = 'v1';
23
+
24
+ function __construct() {
25
+ foreach($this->_available_api_versions as $available_api_version) {
26
+ $this->addEndpointNamespace(
27
+ sprintf('%s\%s', __NAMESPACE__, $available_api_version),
28
+ $available_api_version
29
+ );
30
+ }
31
+ }
32
+
33
+ function init() {
34
+ // admin security token and API version
35
+ add_action(
36
+ 'admin_head',
37
+ array($this, 'setTokenAndAPIVersion')
38
+ );
39
+
40
+ // ajax (logged in users)
41
+ add_action(
42
+ 'wp_ajax_mailpoet',
43
+ array($this, 'setupAjax')
44
+ );
45
+
46
+ // ajax (logged out users)
47
+ add_action(
48
+ 'wp_ajax_nopriv_mailpoet',
49
+ array($this, 'setupAjax')
50
+ );
51
+ }
52
+
53
+ function setupAjax() {
54
+ Hooks::doAction('mailpoet_api_setup', array($this));
55
+ $this->setRequestData($_POST);
56
+
57
+ if($this->checkToken() === false) {
58
+ $error_message = __('Invalid API request.', 'mailpoet');
59
+ $error_response = $this->createErrorResponse(Error::UNAUTHORIZED, $error_message, Response::STATUS_UNAUTHORIZED);
60
+ return $error_response->send();
61
+ }
62
+
63
+ $response = $this->processRoute();
64
+ $response->send();
65
+ }
66
+
67
+ function setRequestData($data) {
68
+ $this->_request_api_version = !empty($data['api_version']) ? $data['api_version']: false;
69
+
70
+ $this->_request_endpoint = isset($data['endpoint'])
71
+ ? Helpers::underscoreToCamelCase(trim($data['endpoint']))
72
+ : null;
73
+
74
+ // JS part of /wp-admin/customize.php does not like a 'method' field in a form widget
75
+ $method_param_name = isset($data['mailpoet_method']) ? 'mailpoet_method' : 'method';
76
+ $this->_request_method = isset($data[$method_param_name])
77
+ ? Helpers::underscoreToCamelCase(trim($data[$method_param_name]))
78
+ : null;
79
+
80
+ $this->_request_token = isset($data['token'])
81
+ ? trim($data['token'])
82
+ : null;
83
+
84
+ if(!$this->_request_endpoint || !$this->_request_method || !$this->_request_api_version) {
85
+ $error_message = __('Invalid API request.', 'mailpoet');
86
+ $error_response = $this->createErrorResponse(Error::BAD_REQUEST, $error_message, Response::STATUS_BAD_REQUEST);
87
+ return $error_response;
88
+ } else if(!empty($this->_endpoint_namespaces[$this->_request_api_version])) {
89
+ foreach($this->_endpoint_namespaces[$this->_request_api_version] as $namespace) {
90
+ $endpoint_class = sprintf(
91
+ '%s\%s',
92
+ $namespace,
93
+ ucfirst($this->_request_endpoint)
94
+ );
95
+ if(class_exists($endpoint_class)) {
96
+ $this->_request_endpoint_class = $endpoint_class;
97
+ break;
98
+ }
99
+ }
100
+ $this->_request_data = isset($data['data'])
101
+ ? stripslashes_deep($data['data'])
102
+ : array();
103
+
104
+ // remove reserved keywords from data
105
+ if(is_array($this->_request_data) && !empty($this->_request_data)) {
106
+ // filter out reserved keywords from data
107
+ $reserved_keywords = array(
108
+ 'token',
109
+ 'endpoint',
110
+ 'method',
111
+ 'api_version',
112
+ 'mailpoet_method', // alias of 'method'
113
+ 'mailpoet_redirect'
114
+ );
115
+ $this->_request_data = array_diff_key(
116
+ $this->_request_data,
117
+ array_flip($reserved_keywords)
118
+ );
119
+ }
120
+ }
121
+ }
122
+
123
+ function processRoute() {
124
+ try {
125
+ if(empty($this->_request_endpoint_class)) {
126
+ throw new \Exception(__('Invalid API endpoint.', 'mailpoet'));
127
+ }
128
+
129
+ $endpoint = new $this->_request_endpoint_class();
130
+
131
+ // check the accessibility of the requested endpoint's action
132
+ // by default, an endpoint's action is considered "private"
133
+ $permissions = $endpoint->permissions;
134
+ if(array_key_exists($this->_request_method, $permissions) === false ||
135
+ $permissions[$this->_request_method] !== Access::ALL
136
+ ) {
137
+ if($this->checkPermissions() === false) {
138
+ $error_message = __('You do not have the required permissions.', 'mailpoet');
139
+ $error_response = $this->createErrorResponse(Error::FORBIDDEN, $error_message, Response::STATUS_FORBIDDEN);
140
+ return $error_response;
141
+ }
142
+ }
143
+
144
+ $response = $endpoint->{$this->_request_method}($this->_request_data);
145
+ return $response;
146
+ } catch(\Exception $e) {
147
+ $error_message = $e->getMessage();
148
+ $error_response = $this->createErrorResponse(Error::BAD_REQUEST, $error_message, Response::STATUS_BAD_REQUEST);
149
+ return $error_response;
150
+ }
151
+ }
152
+
153
+ function checkPermissions() {
154
+ return current_user_can(Env::$required_permission);
155
+ }
156
+
157
+ function checkToken() {
158
+ return wp_verify_nonce($this->_request_token, 'mailpoet_token');
159
+ }
160
+
161
+ function setTokenAndAPIVersion() {
162
+ $global = '<script type="text/javascript">';
163
+ $global .= 'var mailpoet_token = "%s";';
164
+ $global .= 'var mailpoet_api_version = "%s";';
165
+ $global .= '</script>';
166
+ echo sprintf(
167
+ $global,
168
+ Security::generateToken(),
169
+ self::CURRENT_VERSION
170
+ );
171
+ }
172
+
173
+ function addEndpointNamespace($namespace, $version) {
174
+ if(!empty($this->_endpoint_namespaces[$version][$namespace])) return;
175
+ $this->_endpoint_namespaces[$version][] = $namespace;
176
+ }
177
+
178
+ function getEndpointNamespaces() {
179
+ return $this->_endpoint_namespaces;
180
+ }
181
+
182
+ function getRequestedEndpointClass() {
183
+ return $this->_request_endpoint_class;
184
+ }
185
+
186
+ function getRequestedAPIVersion() {
187
+ return $this->_request_api_version;
188
+ }
189
+
190
+ function createErrorResponse($error_type, $error_message, $response_status) {
191
+ $error_response = new ErrorResponse(
192
+ array(
193
+ $error_type => $error_message
194
+ ),
195
+ array(),
196
+ $response_status
197
+ );
198
+ return $error_response;
199
+ }
200
+ }
lib/API/{Access.php → JSON/Access.php} RENAMED
@@ -1,5 +1,5 @@
1
  <?php
2
- namespace MailPoet\API;
3
 
4
  if(!defined('ABSPATH')) exit;
5
 
1
  <?php
2
+ namespace MailPoet\API\JSON;
3
 
4
  if(!defined('ABSPATH')) exit;
5
 
lib/API/{Endpoint.php → JSON/Endpoint.php} RENAMED
@@ -1,5 +1,5 @@
1
  <?php
2
- namespace MailPoet\API;
3
 
4
  if(!defined('ABSPATH')) exit;
5
 
1
  <?php
2
+ namespace MailPoet\API\JSON;
3
 
4
  if(!defined('ABSPATH')) exit;
5
 
lib/API/{Error.php → JSON/Error.php} RENAMED
@@ -1,5 +1,5 @@
1
  <?php
2
- namespace MailPoet\API;
3
 
4
  if(!defined('ABSPATH')) exit;
5
 
1
  <?php
2
+ namespace MailPoet\API\JSON;
3
 
4
  if(!defined('ABSPATH')) exit;
5
 
lib/API/{ErrorResponse.php → JSON/ErrorResponse.php} RENAMED
@@ -1,5 +1,5 @@
1
  <?php
2
- namespace MailPoet\API;
3
 
4
  if(!defined('ABSPATH')) exit;
5
 
1
  <?php
2
+ namespace MailPoet\API\JSON;
3
 
4
  if(!defined('ABSPATH')) exit;
5
 
lib/API/{Response.php → JSON/Response.php} RENAMED
@@ -1,5 +1,5 @@
1
  <?php
2
- namespace MailPoet\API;
3
 
4
  if(!defined('ABSPATH')) exit;
5
 
1
  <?php
2
+ namespace MailPoet\API\JSON;
3
 
4
  if(!defined('ABSPATH')) exit;
5
 
lib/API/{SuccessResponse.php → JSON/SuccessResponse.php} RENAMED
@@ -1,5 +1,5 @@
1
  <?php
2
- namespace MailPoet\API;
3
 
4
  if(!defined('ABSPATH')) exit;
5
 
1
  <?php
2
+ namespace MailPoet\API\JSON;
3
 
4
  if(!defined('ABSPATH')) exit;
5
 
lib/API/{Endpoints → JSON}/index.php RENAMED
File without changes
lib/API/{Endpoints → JSON}/v1/AutomatedLatestContent.php RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
- namespace MailPoet\API\Endpoints\v1;
3
- use MailPoet\API\Endpoint as APIEndpoint;
4
  use MailPoet\WP\Posts as WPPosts;
5
 
6
  if(!defined('ABSPATH')) exit;
1
  <?php
2
+ namespace MailPoet\API\JSON\v1;
3
+ use MailPoet\API\JSON\Endpoint as APIEndpoint;
4
  use MailPoet\WP\Posts as WPPosts;
5
 
6
  if(!defined('ABSPATH')) exit;
lib/API/{Endpoints → JSON}/v1/CustomFields.php RENAMED
@@ -1,7 +1,7 @@
1
  <?php
2
- namespace MailPoet\API\Endpoints\v1;
3
- use MailPoet\API\Endpoint as APIEndpoint;
4
- use MailPoet\API\Error as APIError;
5
  use MailPoet\Models\CustomField;
6
 
7
  if(!defined('ABSPATH')) exit;
1
  <?php
2
+ namespace MailPoet\API\JSON\v1;
3
+ use MailPoet\API\JSON\Endpoint as APIEndpoint;
4
+ use MailPoet\API\JSON\Error as APIError;
5
  use MailPoet\Models\CustomField;
6
 
7
  if(!defined('ABSPATH')) exit;
lib/API/{Endpoints → JSON}/v1/Forms.php RENAMED
@@ -1,7 +1,7 @@
1
  <?php
2
- namespace MailPoet\API\Endpoints\v1;
3
- use MailPoet\API\Endpoint as APIEndpoint;
4
- use MailPoet\API\Error as APIError;
5
 
6
  use MailPoet\Models\Form;
7
  use MailPoet\Models\StatisticsForms;
1
  <?php
2
+ namespace MailPoet\API\JSON\v1;
3
+ use MailPoet\API\JSON\Endpoint as APIEndpoint;
4
+ use MailPoet\API\JSON\Error as APIError;
5
 
6
  use MailPoet\Models\Form;
7
  use MailPoet\Models\StatisticsForms;
lib/API/{Endpoints → JSON}/v1/ImportExport.php RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
- namespace MailPoet\API\Endpoints\v1;
3
- use MailPoet\API\Endpoint as APIEndpoint;
4
 
5
  use MailPoet\Subscribers\ImportExport\Import\MailChimp;
6
  use MailPoet\Models\Segment;
1
  <?php
2
+ namespace MailPoet\API\JSON\v1;
3
+ use MailPoet\API\JSON\Endpoint as APIEndpoint;
4
 
5
  use MailPoet\Subscribers\ImportExport\Import\MailChimp;
6
  use MailPoet\Models\Segment;
lib/API/{Endpoints → JSON}/v1/Mailer.php RENAMED
@@ -1,7 +1,7 @@
1
  <?php
2
- namespace MailPoet\API\Endpoints\v1;
3
- use MailPoet\API\Endpoint as APIEndpoint;
4
- use MailPoet\API\Error as APIError;
5
  use MailPoet\Mailer\MailerLog;
6
 
7
  if(!defined('ABSPATH')) exit;
1
  <?php
2
+ namespace MailPoet\API\JSON\v1;
3
+ use MailPoet\API\JSON\Endpoint as APIEndpoint;
4
+ use MailPoet\API\JSON\Error as APIError;
5
  use MailPoet\Mailer\MailerLog;
6
 
7
  if(!defined('ABSPATH')) exit;
lib/API/{Endpoints → JSON}/v1/NewsletterTemplates.php RENAMED
@@ -1,7 +1,7 @@
1
  <?php
2
- namespace MailPoet\API\Endpoints\v1;
3
- use MailPoet\API\Endpoint as APIEndpoint;
4
- use MailPoet\API\Error as APIError;
5
 
6
  use MailPoet\Models\NewsletterTemplate;
7
 
1
  <?php
2
+ namespace MailPoet\API\JSON\v1;
3
+ use MailPoet\API\JSON\Endpoint as APIEndpoint;
4
+ use MailPoet\API\JSON\Error as APIError;
5
 
6
  use MailPoet\Models\NewsletterTemplate;
7
 
lib/API/{Endpoints → JSON}/v1/Newsletters.php RENAMED
@@ -1,8 +1,8 @@
1
  <?php
2
- namespace MailPoet\API\Endpoints\v1;
3
 
4
- use MailPoet\API\Endpoint as APIEndpoint;
5
- use MailPoet\API\Error as APIError;
6
  use MailPoet\Listing;
7
  use MailPoet\Models\SendingQueue;
8
  use MailPoet\Models\Setting;
1
  <?php
2
+ namespace MailPoet\API\JSON\v1;
3
 
4
+ use MailPoet\API\JSON\Endpoint as APIEndpoint;
5
+ use MailPoet\API\JSON\Error as APIError;
6
  use MailPoet\Listing;
7
  use MailPoet\Models\SendingQueue;
8
  use MailPoet\Models\Setting;
lib/API/{Endpoints → JSON}/v1/Segments.php RENAMED
@@ -1,7 +1,7 @@
1
  <?php
2
- namespace MailPoet\API\Endpoints\v1;
3
- use MailPoet\API\Endpoint as APIEndpoint;
4
- use MailPoet\API\Error as APIError;
5
 
6
  use MailPoet\Models\Segment;
7
  use MailPoet\Listing;
1
  <?php
2
+ namespace MailPoet\API\JSON\v1;
3
+ use MailPoet\API\JSON\Endpoint as APIEndpoint;
4
+ use MailPoet\API\JSON\Error as APIError;
5
 
6
  use MailPoet\Models\Segment;
7
  use MailPoet\Listing;
lib/API/{Endpoints → JSON}/v1/SendingQueue.php RENAMED
@@ -1,7 +1,7 @@
1
  <?php
2
- namespace MailPoet\API\Endpoints\v1;
3
- use MailPoet\API\Endpoint as APIEndpoint;
4
- use MailPoet\API\Error as APIError;
5
 
6
  use MailPoet\Mailer\Mailer;
7
  use MailPoet\Models\Newsletter;
1
  <?php
2
+ namespace MailPoet\API\JSON\v1;
3
+ use MailPoet\API\JSON\Endpoint as APIEndpoint;
4
+ use MailPoet\API\JSON\Error as APIError;
5
 
6
  use MailPoet\Mailer\Mailer;
7
  use MailPoet\Models\Newsletter;
lib/API/{Endpoints → JSON}/v1/Services.php RENAMED
@@ -1,8 +1,8 @@
1
  <?php
2
- namespace MailPoet\API\Endpoints\v1;
3
 
4
- use MailPoet\API\Endpoint as APIEndpoint;
5
- use MailPoet\API\Error as APIError;
6
  use MailPoet\Services\Bridge;
7
  use MailPoet\Util\License\License;
8
  use MailPoet\WP\DateTime;
1
  <?php
2
+ namespace MailPoet\API\JSON\v1;
3
 
4
+ use MailPoet\API\JSON\Endpoint as APIEndpoint;
5
+ use MailPoet\API\JSON\Error as APIError;
6
  use MailPoet\Services\Bridge;
7
  use MailPoet\Util\License\License;
8
  use MailPoet\WP\DateTime;
lib/API/{Endpoints → JSON}/v1/Settings.php RENAMED
@@ -1,8 +1,8 @@
1
  <?php
2
- namespace MailPoet\API\Endpoints\v1;
3
 
4
- use MailPoet\API\Endpoint as APIEndpoint;
5
- use MailPoet\API\Error as APIError;
6
  use MailPoet\Models\Setting;
7
  use MailPoet\Services\Bridge;
8
 
1
  <?php
2
+ namespace MailPoet\API\JSON\v1;
3
 
4
+ use MailPoet\API\JSON\Endpoint as APIEndpoint;
5
+ use MailPoet\API\JSON\Error as APIError;
6
  use MailPoet\Models\Setting;
7
  use MailPoet\Services\Bridge;
8
 
lib/API/{Endpoints → JSON}/v1/Setup.php RENAMED
@@ -1,7 +1,7 @@
1
  <?php
2
- namespace MailPoet\API\Endpoints\v1;
3
 
4
- use MailPoet\API\Endpoint as APIEndpoint;
5
  use MailPoet\Config\Activator;
6
  use MailPoet\WP\Hooks;
7
 
1
  <?php
2
+ namespace MailPoet\API\JSON\v1;
3
 
4
+ use MailPoet\API\JSON\Endpoint as APIEndpoint;
5
  use MailPoet\Config\Activator;
6
  use MailPoet\WP\Hooks;
7
 
lib/API/{Endpoints → JSON}/v1/Subscribers.php RENAMED
@@ -1,8 +1,8 @@
1
  <?php
2
- namespace MailPoet\API\Endpoints\v1;
3
- use MailPoet\API\Endpoint as APIEndpoint;
4
- use MailPoet\API\Error as APIError;
5
- use MailPoet\API\Access as APIAccess;
6
 
7
  use MailPoet\Listing;
8
  use MailPoet\Models\Subscriber;
1
  <?php
2
+ namespace MailPoet\API\JSON\v1;
3
+ use MailPoet\API\JSON\Endpoint as APIEndpoint;
4
+ use MailPoet\API\JSON\Error as APIError;
5
+ use MailPoet\API\JSON\Access as APIAccess;
6
 
7
  use MailPoet\Listing;
8
  use MailPoet\Models\Subscriber;
lib/API/{Endpoints → JSON}/v1/index.php RENAMED
File without changes
lib/API/MP/index.php ADDED
File without changes
lib/API/MP/v1/API.php ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace MailPoet\API\MP\v1;
3
+
4
+ use MailPoet\Models\CustomField;
5
+ use MailPoet\Models\Segment;
6
+ use MailPoet\Models\Subscriber;
7
+ use MailPoet\Models\SubscriberSegment;
8
+ use MailPoet\Newsletter\Scheduler\Scheduler;
9
+
10
+ if(!defined('ABSPATH')) exit;
11
+
12
+ class API {
13
+ function getSubscriberFields() {
14
+ $data = array(
15
+ array(
16
+ 'id' => 'email',
17
+ 'name' => __('Email', 'mailpoet')
18
+ ),
19
+ array(
20
+ 'id' => 'first_name',
21
+ 'name' => __('First name', 'mailpoet')
22
+ ),
23
+ array(
24
+ 'id' => 'last_name',
25
+ 'name' => __('Last name', 'mailpoet')
26
+ )
27
+ );
28
+
29
+ $custom_fields = CustomField::selectMany(array('id', 'name'))->findMany();
30
+ foreach($custom_fields as $custom_field) {
31
+ $data[] = array(
32
+ 'id' => 'cf_' . $custom_field->id,
33
+ 'name' => $custom_field->name
34
+ );
35
+ }
36
+
37
+ return $data;
38
+ }
39
+
40
+ function subscribeToList($subscriber_id, $segment_id) {
41
+ return $this->subscribeToLists($subscriber_id, array($segment_id));
42
+ }
43
+
44
+ function subscribeToLists($subscriber_id, array $segments_ids) {
45
+ $subscriber = Subscriber::findOne($subscriber_id);
46
+ // throw exception when subscriber does not exist
47
+ if(!$subscriber) {
48
+ throw new \Exception(__('This subscriber does not exist.', 'mailpoet'));
49
+ }
50
+
51
+ // throw exception when none of the segments exist
52
+ $found_segments = Segment::whereIn('id', $segments_ids)->findMany();
53
+ if(!$found_segments) {
54
+ throw new \Exception(__('These lists do not exist.', 'mailpoet'));
55
+ }
56
+
57
+ // throw exception when trying to subscribe to a WP Users segment
58
+ $found_segments_ids = array();
59
+ foreach($found_segments as $found_segment) {
60
+ if($found_segment->type === Segment::TYPE_WP_USERS) {
61
+ throw new \Exception(__(sprintf("Can't subscribe to a WordPress Users list with ID %d.", $found_segment->id), 'mailpoet'));
62
+ }
63
+ $found_segments_ids[] = $found_segment->id;
64
+ }
65
+
66
+ // throw an exception when one or more segments do not exist
67
+ if(count($found_segments_ids) !== count($segments_ids)) {
68
+ $missing_ids = array_values(array_diff($segments_ids, $found_segments_ids));
69
+ throw new \Exception(__(sprintf('Lists with ID %s do not exist.', implode(', ', $missing_ids)), 'mailpoet'));
70
+ }
71
+
72
+ SubscriberSegment::subscribeToSegments($subscriber, $found_segments_ids);
73
+ return $subscriber->withCustomFields()->withSubscriptions()->asArray();
74
+ }
75
+
76
+ function getLists() {
77
+ return Segment::whereNotEqual('type', Segment::TYPE_WP_USERS)->findArray();
78
+ }
79
+
80
+ function addSubscriber(array $subscriber, $segments = array(), $options = array()) {
81
+ $send_confirmation_email = (isset($options['send_confirmation_email']) && $options['send_confirmation_email'] === false) ? false : true;
82
+ $schedule_welcome_email = (isset($options['schedule_welcome_email']) && $options['schedule_welcome_email'] === false) ? false : true;
83
+
84
+ // throw exception when subscriber email is missing
85
+ if(empty($subscriber['email'])) {
86
+ throw new \Exception(
87
+ __('Subscriber email address is required.', 'mailpoet')
88
+ );
89
+ }
90
+
91
+ // throw exception when subscriber already exists
92
+ if(Subscriber::findOne($subscriber['email'])) {
93
+ throw new \Exception(
94
+ __('This subscriber already exists.', 'mailpoet')
95
+ );
96
+ }
97
+
98
+ // separate data into default and custom fields
99
+ list($default_fields, $custom_fields) = Subscriber::extractCustomFieldsFromFromObject($subscriber);
100
+ // if some required default fields are missing, set their values
101
+ $default_fields = Subscriber::setRequiredFieldsDefaultValues($default_fields);
102
+
103
+ // add subscriber
104
+ $new_subscriber = Subscriber::create();
105
+ $new_subscriber->hydrate($default_fields);
106
+ $new_subscriber->save();
107
+ if($new_subscriber->getErrors() !== false) {
108
+ throw new \Exception(
109
+ __(sprintf('Failed to add subscriber: %s', strtolower(implode(', ', $new_subscriber->getErrors()))), 'mailpoet')
110
+ );
111
+ }
112
+ if(!empty($custom_fields)) {
113
+ $new_subscriber->saveCustomFields($custom_fields);
114
+ }
115
+
116
+ // subscribe to segments and optionally: 1) send confirmation email, 2) schedule welcome email(s)
117
+ if(!empty($segments)) {
118
+ $this->subscribeToLists($new_subscriber->id, $segments);
119
+
120
+ // send confirmation email
121
+ if($send_confirmation_email && $new_subscriber->status === Subscriber::STATUS_UNCONFIRMED) {
122
+ $this->sendConfirmationEmail($new_subscriber);
123
+ }
124
+
125
+ // schedule welcome email(s)
126
+ if($schedule_welcome_email) {
127
+ Scheduler::scheduleSubscriberWelcomeNotification($new_subscriber->id, $segments);
128
+ }
129
+ }
130
+ return $new_subscriber->withCustomFields()->withSubscriptions()->asArray();
131
+ }
132
+ }
lib/API/MP/v1/index.php ADDED
File without changes
lib/Config/Initializer.php CHANGED
@@ -98,7 +98,7 @@ class Initializer {
98
  }
99
 
100
  try {
101
- $this->setupAPI();
102
  $this->setupRouter();
103
  $this->setupPages();
104
  } catch(\Exception $e) {
@@ -171,9 +171,8 @@ class Initializer {
171
  $hooks->init();
172
  }
173
 
174
- function setupAPI() {
175
- $api = new API\API();
176
- $api->init();
177
  }
178
 
179
  function setupRouter() {
98
  }
99
 
100
  try {
101
+ $this->setupJSONAPI();
102
  $this->setupRouter();
103
  $this->setupPages();
104
  } catch(\Exception $e) {
171
  $hooks->init();
172
  }
173
 
174
+ function setupJSONAPI() {
175
+ API\API::JSON()->init();
 
176
  }
177
 
178
  function setupRouter() {
lib/Form/Widget.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  namespace MailPoet\Form;
3
- use MailPoet\API\API;
4
  use MailPoet\Config\Renderer;
5
  use MailPoet\Models\Form;
6
  use MailPoet\Form\Renderer as FormRenderer;
1
  <?php
2
  namespace MailPoet\Form;
3
+ use MailPoet\API\JSON\API;
4
  use MailPoet\Config\Renderer;
5
  use MailPoet\Models\Form;
6
  use MailPoet\Form\Renderer as FormRenderer;
lib/Models/CustomField.php CHANGED
@@ -7,6 +7,12 @@ if(!defined('ABSPATH')) exit;
7
 
8
  class CustomField extends Model {
9
  public static $_table = MP_CUSTOM_FIELDS_TABLE;
 
 
 
 
 
 
10
 
11
  function __construct() {
12
  parent::__construct();
@@ -43,7 +49,7 @@ class CustomField extends Model {
43
 
44
  function formatValue($value = null) {
45
  // format custom field data depending on type
46
- if(is_array($value) && $this->type === 'date' ) {
47
  $custom_field_data = $this->asArray();
48
  $date_format = $custom_field_data['params']['date_format'];
49
  $date_type = (isset($custom_field_data['params']['date_type'])
7
 
8
  class CustomField extends Model {
9
  public static $_table = MP_CUSTOM_FIELDS_TABLE;
10
+ const TYPE_DATE = 'date';
11
+ const TYPE_TEXT = 'text';
12
+ const TYPE_TEXTAREA = 'textarea';
13
+ const TYPE_RADIO = 'radio';
14
+ const TYPE_CHECKBOX = 'checkbox';
15
+ const TYPE_SELECT = 'select';
16
 
17
  function __construct() {
18
  parent::__construct();
49
 
50
  function formatValue($value = null) {
51
  // format custom field data depending on type
52
+ if(is_array($value) && $this->type === self::TYPE_DATE) {
53
  $custom_field_data = $this->asArray();
54
  $date_format = $custom_field_data['params']['date_format'];
55
  $date_type = (isset($custom_field_data['params']['date_type'])
lib/Models/Segment.php CHANGED
@@ -5,6 +5,8 @@ if(!defined('ABSPATH')) exit;
5
 
6
  class Segment extends Model {
7
  static $_table = MP_SEGMENTS_TABLE;
 
 
8
 
9
  function __construct() {
10
  parent::__construct();
@@ -103,7 +105,7 @@ class Segment extends Model {
103
  }
104
 
105
  static function getWPSegment() {
106
- $wp_segment = self::where('type', 'wp_users')->findOne();
107
 
108
  if($wp_segment === false) {
109
  // create the wp users segment
@@ -148,7 +150,7 @@ class Segment extends Model {
148
  return $orm;
149
  }
150
 
151
- static function getSegmentsWithSubscriberCount($type = 'default') {
152
  $query = self::selectMany(array(self::$_table.'.id', self::$_table.'.name'))
153
  ->selectExpr(
154
  self::$_table.'.*, ' .
@@ -227,7 +229,7 @@ class Segment extends Model {
227
  }
228
 
229
  static function getPublic() {
230
- return self::getPublished()->where('type', 'default')->orderByAsc('name');
231
  }
232
 
233
  static function bulkTrash($orm) {
@@ -236,7 +238,7 @@ class Segment extends Model {
236
  'UPDATE `' . Segment::$_table . '`',
237
  'SET `deleted_at` = NOW()',
238
  'WHERE `id` IN ('.rtrim(str_repeat('?,', count($ids)), ',').')',
239
- 'AND `type` = "default"'
240
  )), $ids);
241
  });
242
 
@@ -247,7 +249,7 @@ class Segment extends Model {
247
  $count = parent::bulkAction($orm, function($ids) {
248
  // delete segments (only default)
249
  Segment::whereIn('id', $ids)
250
- ->where('type', 'default')
251
  ->deleteMany();
252
  });
253
 
5
 
6
  class Segment extends Model {
7
  static $_table = MP_SEGMENTS_TABLE;
8
+ const TYPE_WP_USERS = 'wp_users';
9
+ const TYPE_DEFAULT = 'default';
10
 
11
  function __construct() {
12
  parent::__construct();
105
  }
106
 
107
  static function getWPSegment() {
108
+ $wp_segment = self::where('type', self::TYPE_WP_USERS)->findOne();
109
 
110
  if($wp_segment === false) {
111
  // create the wp users segment
150
  return $orm;
151
  }
152
 
153
+ static function getSegmentsWithSubscriberCount($type = self::TYPE_DEFAULT) {
154
  $query = self::selectMany(array(self::$_table.'.id', self::$_table.'.name'))
155
  ->selectExpr(
156
  self::$_table.'.*, ' .
229
  }
230
 
231
  static function getPublic() {
232
+ return self::getPublished()->where('type', self::TYPE_DEFAULT)->orderByAsc('name');
233
  }
234
 
235
  static function bulkTrash($orm) {
238
  'UPDATE `' . Segment::$_table . '`',
239
  'SET `deleted_at` = NOW()',
240
  'WHERE `id` IN ('.rtrim(str_repeat('?,', count($ids)), ',').')',
241
+ 'AND `type` = "' . Segment::TYPE_DEFAULT . '"'
242
  )), $ids);
243
  });
244
 
249
  $count = parent::bulkAction($orm, function($ids) {
250
  // delete segments (only default)
251
  Segment::whereIn('id', $ids)
252
+ ->where('type', Segment::TYPE_DEFAULT)
253
  ->deleteMany();
254
  });
255
 
lib/Models/Subscriber.php CHANGED
@@ -491,27 +491,10 @@ class Subscriber extends Model {
491
  unset($data['segments']);
492
  }
493
 
494
- if($subscriber === false) {
495
- // fields that must exist
496
- $not_null_fields = array(
497
- 'first_name' => '',
498
- 'last_name' => ''
499
- );
500
- foreach($not_null_fields as $field => $value) {
501
- if(!isset($data[$field])) {
502
- $data[$field] = $value;
503
- }
504
- }
505
- }
506
 
507
- // custom fields
508
- $custom_fields = array();
509
- foreach($data as $key => $value) {
510
- if(strpos($key, 'cf_') === 0) {
511
- $custom_fields[(int)substr($key, 3)] = $value;
512
- unset($data[$key]);
513
- }
514
- }
515
 
516
  // wipe any unconfirmed data at this point
517
  $data['unconfirmed_data'] = null;
@@ -884,4 +867,28 @@ class Subscriber extends Model {
884
  }, $subscribers)
885
  );
886
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
887
  }
491
  unset($data['segments']);
492
  }
493
 
494
+ $data = self::setRequiredFieldsDefaultValues($data);
 
 
 
 
 
 
 
 
 
 
 
495
 
496
+ // get custom fields
497
+ list($data, $custom_fields) = self::extractCustomFieldsFromFromObject($data);
 
 
 
 
 
 
498
 
499
  // wipe any unconfirmed data at this point
500
  $data['unconfirmed_data'] = null;
867
  }, $subscribers)
868
  );
869
  }
870
+
871
+ static function setRequiredFieldsDefaultValues($data) {
872
+ $required_field_default_values = array(
873
+ 'first_name' => '',
874
+ 'last_name' => ''
875
+ );
876
+ foreach($required_field_default_values as $field => $value) {
877
+ if(!isset($data[$field])) {
878
+ $data[$field] = $value;
879
+ }
880
+ }
881
+ return $data;
882
+ }
883
+
884
+ static function extractCustomFieldsFromFromObject($data) {
885
+ $custom_fields = array();
886
+ foreach($data as $key => $value) {
887
+ if(strpos($key, 'cf_') === 0) {
888
+ $custom_fields[(int)substr($key, 3)] = $value;
889
+ unset($data[$key]);
890
+ }
891
+ }
892
+ return array($data, $custom_fields);
893
+ }
894
  }
lib/Subscription/Form.php CHANGED
@@ -1,8 +1,8 @@
1
  <?php
2
  namespace MailPoet\Subscription;
3
 
4
- use MailPoet\API\API;
5
- use MailPoet\API\Endpoints\Subscribers;
6
  use MailPoet\API\Response as APIResponse;
7
  use MailPoet\Util\Url;
8
 
1
  <?php
2
  namespace MailPoet\Subscription;
3
 
4
+ use MailPoet\API\JSON\API;
5
+ use MailPoet\API\JSON\Endpoints\Subscribers;
6
  use MailPoet\API\Response as APIResponse;
7
  use MailPoet\Util\Url;
8
 
mailpoet.php CHANGED
@@ -4,13 +4,13 @@ if(!defined('ABSPATH')) exit;
4
 
5
  /*
6
  * Plugin Name: MailPoet
7
- * Version: 3.0.0-beta.31
8
  * Plugin URI: http://www.mailpoet.com
9
  * Description: Create and send beautiful email newsletters, autoresponders, and post notifications without leaving WordPress. This is a beta version of our brand new plugin!
10
  * Author: MailPoet
11
  * Author URI: http://www.mailpoet.com
12
  * Requires at least: 4.6
13
- * Tested up to: 4.7.4
14
  *
15
  * Text Domain: mailpoet
16
  * Domain Path: /lang/
@@ -21,7 +21,7 @@ if(!defined('ABSPATH')) exit;
21
  */
22
 
23
  $mailpoet_plugin = array(
24
- 'version' => '3.0.0-beta.31',
25
  'filename' => __FILE__,
26
  'path' => dirname(__FILE__),
27
  'autoloader' => dirname(__FILE__) . '/vendor/autoload.php',
4
 
5
  /*
6
  * Plugin Name: MailPoet
7
+ * Version: 3.0.0-beta.32
8
  * Plugin URI: http://www.mailpoet.com
9
  * Description: Create and send beautiful email newsletters, autoresponders, and post notifications without leaving WordPress. This is a beta version of our brand new plugin!
10
  * Author: MailPoet
11
  * Author URI: http://www.mailpoet.com
12
  * Requires at least: 4.6
13
+ * Tested up to: 4.7.5
14
  *
15
  * Text Domain: mailpoet
16
  * Domain Path: /lang/
21
  */
22
 
23
  $mailpoet_plugin = array(
24
+ 'version' => '3.0.0-beta.32',
25
  'filename' => __FILE__,
26
  'path' => dirname(__FILE__),
27
  'autoloader' => dirname(__FILE__) . '/vendor/autoload.php',
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: mailpoet, wysija
3
  Tags: newsletter, email, welcome email, post notification, autoresponder, signup, subscription, SMTP
4
  Requires at least: 4.6
5
- Tested up to: 4.7.4
6
- Stable tag: 3.0.0-beta.31
7
  Create and send beautiful emails and newsletters from WordPress.
8
 
9
  == Description ==
@@ -91,13 +91,16 @@ Our [support site](https://beta.docs.mailpoet.com) has plenty of articles. You c
91
 
92
  == Changelog ==
93
 
 
 
 
94
  = 3.0.0-beta.31 - 2017-05-16 =
95
  * Improved: automated latest content/post search boxes in the editor now return up to 50 results;
96
  * Improved: sending progress bar got a new look;
97
  * Improved: added plugin translation to Persian (Iran) language. Thanks Ali Reza Karami!;
98
  * Fixed: submission of subscription forms with list selection or non-text custom fields works again. Thanks Stefan!;
99
  * Fixed: subscription management form works fine again;
100
- * Fixed: invalid license key warnings are temporary hidden if a key is empty;
101
  * Fixed: newsletter link hashes are much less likely to collide. Thanks Sherrie!
102
 
103
  = 3.0.0-beta.30 - 2017-05-09 =
2
  Contributors: mailpoet, wysija
3
  Tags: newsletter, email, welcome email, post notification, autoresponder, signup, subscription, SMTP
4
  Requires at least: 4.6
5
+ Tested up to: 4.7.5
6
+ Stable tag: 3.0.0-beta.32
7
  Create and send beautiful emails and newsletters from WordPress.
8
 
9
  == Description ==
91
 
92
  == Changelog ==
93
 
94
+ = 3.0.0-beta.32 - 2017-05-23 =
95
+ * Added: API methods for 3rd party plugins to add subscribers to MailPoet. Which plugins should we connect to?
96
+
97
  = 3.0.0-beta.31 - 2017-05-16 =
98
  * Improved: automated latest content/post search boxes in the editor now return up to 50 results;
99
  * Improved: sending progress bar got a new look;
100
  * Improved: added plugin translation to Persian (Iran) language. Thanks Ali Reza Karami!;
101
  * Fixed: submission of subscription forms with list selection or non-text custom fields works again. Thanks Stefan!;
102
  * Fixed: subscription management form works fine again;
103
+ * Fixed: invalid license key warnings are temporarily hidden if a key is empty;
104
  * Fixed: newsletter link hashes are much less likely to collide. Thanks Sherrie!
105
 
106
  = 3.0.0-beta.30 - 2017-05-09 =
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInitc76a9eae629b371d4ea958147a147184::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInitf7070d6c9209c4d83defebc2b9edd278::getLoader();
vendor/composer/ClassLoader.php CHANGED
@@ -55,6 +55,7 @@ class ClassLoader
55
  private $classMap = array();
56
  private $classMapAuthoritative = false;
57
  private $missingClasses = array();
 
58
 
59
  public function getPrefixes()
60
  {
@@ -271,6 +272,26 @@ class ClassLoader
271
  return $this->classMapAuthoritative;
272
  }
273
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
  /**
275
  * Registers this instance as an autoloader.
276
  *
@@ -313,11 +334,6 @@ class ClassLoader
313
  */
314
  public function findFile($class)
315
  {
316
- // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
317
- if ('\\' == $class[0]) {
318
- $class = substr($class, 1);
319
- }
320
-
321
  // class map lookup
322
  if (isset($this->classMap[$class])) {
323
  return $this->classMap[$class];
@@ -325,6 +341,12 @@ class ClassLoader
325
  if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
326
  return false;
327
  }
 
 
 
 
 
 
328
 
329
  $file = $this->findFileWithExtension($class, '.php');
330
 
@@ -333,6 +355,10 @@ class ClassLoader
333
  $file = $this->findFileWithExtension($class, '.hh');
334
  }
335
 
 
 
 
 
336
  if (false === $file) {
337
  // Remember that this class does not exist.
338
  $this->missingClasses[$class] = true;
55
  private $classMap = array();
56
  private $classMapAuthoritative = false;
57
  private $missingClasses = array();
58
+ private $apcuPrefix;
59
 
60
  public function getPrefixes()
61
  {
272
  return $this->classMapAuthoritative;
273
  }
274
 
275
+ /**
276
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
277
+ *
278
+ * @param string|null $apcuPrefix
279
+ */
280
+ public function setApcuPrefix($apcuPrefix)
281
+ {
282
+ $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
283
+ }
284
+
285
+ /**
286
+ * The APCu prefix in use, or null if APCu caching is not enabled.
287
+ *
288
+ * @return string|null
289
+ */
290
+ public function getApcuPrefix()
291
+ {
292
+ return $this->apcuPrefix;
293
+ }
294
+
295
  /**
296
  * Registers this instance as an autoloader.
297
  *
334
  */
335
  public function findFile($class)
336
  {
 
 
 
 
 
337
  // class map lookup
338
  if (isset($this->classMap[$class])) {
339
  return $this->classMap[$class];
341
  if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
342
  return false;
343
  }
344
+ if (null !== $this->apcuPrefix) {
345
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
346
+ if ($hit) {
347
+ return $file;
348
+ }
349
+ }
350
 
351
  $file = $this->findFileWithExtension($class, '.php');
352
 
355
  $file = $this->findFileWithExtension($class, '.hh');
356
  }
357
 
358
+ if (null !== $this->apcuPrefix) {
359
+ apcu_add($this->apcuPrefix.$class, $file);
360
+ }
361
+
362
  if (false === $file) {
363
  // Remember that this class does not exist.
364
  $this->missingClasses[$class] = true;
vendor/composer/autoload_classmap.php CHANGED
@@ -26,25 +26,27 @@ return array(
26
  'IdiormString' => $vendorDir . '/j4mie/idiorm/idiorm.php',
27
  'IdiormStringException' => $vendorDir . '/j4mie/idiorm/idiorm.php',
28
  'MailPoet\\API\\API' => $baseDir . '/lib/API/API.php',
29
- 'MailPoet\\API\\Access' => $baseDir . '/lib/API/Access.php',
30
- 'MailPoet\\API\\Endpoint' => $baseDir . '/lib/API/Endpoint.php',
31
- 'MailPoet\\API\\Endpoints\\v1\\AutomatedLatestContent' => $baseDir . '/lib/API/Endpoints/v1/AutomatedLatestContent.php',
32
- 'MailPoet\\API\\Endpoints\\v1\\CustomFields' => $baseDir . '/lib/API/Endpoints/v1/CustomFields.php',
33
- 'MailPoet\\API\\Endpoints\\v1\\Forms' => $baseDir . '/lib/API/Endpoints/v1/Forms.php',
34
- 'MailPoet\\API\\Endpoints\\v1\\ImportExport' => $baseDir . '/lib/API/Endpoints/v1/ImportExport.php',
35
- 'MailPoet\\API\\Endpoints\\v1\\Mailer' => $baseDir . '/lib/API/Endpoints/v1/Mailer.php',
36
- 'MailPoet\\API\\Endpoints\\v1\\NewsletterTemplates' => $baseDir . '/lib/API/Endpoints/v1/NewsletterTemplates.php',
37
- 'MailPoet\\API\\Endpoints\\v1\\Newsletters' => $baseDir . '/lib/API/Endpoints/v1/Newsletters.php',
38
- 'MailPoet\\API\\Endpoints\\v1\\Segments' => $baseDir . '/lib/API/Endpoints/v1/Segments.php',
39
- 'MailPoet\\API\\Endpoints\\v1\\SendingQueue' => $baseDir . '/lib/API/Endpoints/v1/SendingQueue.php',
40
- 'MailPoet\\API\\Endpoints\\v1\\Services' => $baseDir . '/lib/API/Endpoints/v1/Services.php',
41
- 'MailPoet\\API\\Endpoints\\v1\\Settings' => $baseDir . '/lib/API/Endpoints/v1/Settings.php',
42
- 'MailPoet\\API\\Endpoints\\v1\\Setup' => $baseDir . '/lib/API/Endpoints/v1/Setup.php',
43
- 'MailPoet\\API\\Endpoints\\v1\\Subscribers' => $baseDir . '/lib/API/Endpoints/v1/Subscribers.php',
44
- 'MailPoet\\API\\Error' => $baseDir . '/lib/API/Error.php',
45
- 'MailPoet\\API\\ErrorResponse' => $baseDir . '/lib/API/ErrorResponse.php',
46
- 'MailPoet\\API\\Response' => $baseDir . '/lib/API/Response.php',
47
- 'MailPoet\\API\\SuccessResponse' => $baseDir . '/lib/API/SuccessResponse.php',
 
 
48
  'MailPoet\\Analytics\\Reporter' => $baseDir . '/lib/Analytics/Reporter.php',
49
  'MailPoet\\Config\\Activator' => $baseDir . '/lib/Config/Activator.php',
50
  'MailPoet\\Config\\Analytics' => $baseDir . '/lib/Config/Analytics.php',
26
  'IdiormString' => $vendorDir . '/j4mie/idiorm/idiorm.php',
27
  'IdiormStringException' => $vendorDir . '/j4mie/idiorm/idiorm.php',
28
  'MailPoet\\API\\API' => $baseDir . '/lib/API/API.php',
29
+ 'MailPoet\\API\\JSON\\API' => $baseDir . '/lib/API/JSON/API.php',
30
+ 'MailPoet\\API\\JSON\\Access' => $baseDir . '/lib/API/JSON/Access.php',
31
+ 'MailPoet\\API\\JSON\\Endpoint' => $baseDir . '/lib/API/JSON/Endpoint.php',
32
+ 'MailPoet\\API\\JSON\\Error' => $baseDir . '/lib/API/JSON/Error.php',
33
+ 'MailPoet\\API\\JSON\\ErrorResponse' => $baseDir . '/lib/API/JSON/ErrorResponse.php',
34
+ 'MailPoet\\API\\JSON\\Response' => $baseDir . '/lib/API/JSON/Response.php',
35
+ 'MailPoet\\API\\JSON\\SuccessResponse' => $baseDir . '/lib/API/JSON/SuccessResponse.php',
36
+ 'MailPoet\\API\\JSON\\v1\\AutomatedLatestContent' => $baseDir . '/lib/API/JSON/v1/AutomatedLatestContent.php',
37
+ 'MailPoet\\API\\JSON\\v1\\CustomFields' => $baseDir . '/lib/API/JSON/v1/CustomFields.php',
38
+ 'MailPoet\\API\\JSON\\v1\\Forms' => $baseDir . '/lib/API/JSON/v1/Forms.php',
39
+ 'MailPoet\\API\\JSON\\v1\\ImportExport' => $baseDir . '/lib/API/JSON/v1/ImportExport.php',
40
+ 'MailPoet\\API\\JSON\\v1\\Mailer' => $baseDir . '/lib/API/JSON/v1/Mailer.php',
41
+ 'MailPoet\\API\\JSON\\v1\\NewsletterTemplates' => $baseDir . '/lib/API/JSON/v1/NewsletterTemplates.php',
42
+ 'MailPoet\\API\\JSON\\v1\\Newsletters' => $baseDir . '/lib/API/JSON/v1/Newsletters.php',
43
+ 'MailPoet\\API\\JSON\\v1\\Segments' => $baseDir . '/lib/API/JSON/v1/Segments.php',
44
+ 'MailPoet\\API\\JSON\\v1\\SendingQueue' => $baseDir . '/lib/API/JSON/v1/SendingQueue.php',
45
+ 'MailPoet\\API\\JSON\\v1\\Services' => $baseDir . '/lib/API/JSON/v1/Services.php',
46
+ 'MailPoet\\API\\JSON\\v1\\Settings' => $baseDir . '/lib/API/JSON/v1/Settings.php',
47
+ 'MailPoet\\API\\JSON\\v1\\Setup' => $baseDir . '/lib/API/JSON/v1/Setup.php',
48
+ 'MailPoet\\API\\JSON\\v1\\Subscribers' => $baseDir . '/lib/API/JSON/v1/Subscribers.php',
49
+ 'MailPoet\\API\\MP\\v1\\API' => $baseDir . '/lib/API/MP/v1/API.php',
50
  'MailPoet\\Analytics\\Reporter' => $baseDir . '/lib/Analytics/Reporter.php',
51
  'MailPoet\\Config\\Activator' => $baseDir . '/lib/Config/Activator.php',
52
  'MailPoet\\Config\\Analytics' => $baseDir . '/lib/Config/Analytics.php',
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInitc76a9eae629b371d4ea958147a147184
6
  {
7
  private static $loader;
8
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInitc76a9eae629b371d4ea958147a147184
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInitc76a9eae629b371d4ea958147a147184', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInitc76a9eae629b371d4ea958147a147184', 'loadClassLoader'));
25
 
26
- $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
- call_user_func(\Composer\Autoload\ComposerStaticInitc76a9eae629b371d4ea958147a147184::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
@@ -48,19 +48,19 @@ class ComposerAutoloaderInitc76a9eae629b371d4ea958147a147184
48
  $loader->register(true);
49
 
50
  if ($useStaticLoader) {
51
- $includeFiles = Composer\Autoload\ComposerStaticInitc76a9eae629b371d4ea958147a147184::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
- composerRequirec76a9eae629b371d4ea958147a147184($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
- function composerRequirec76a9eae629b371d4ea958147a147184($fileIdentifier, $file)
64
  {
65
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
  require $file;
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInitf7070d6c9209c4d83defebc2b9edd278
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInitf7070d6c9209c4d83defebc2b9edd278', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInitf7070d6c9209c4d83defebc2b9edd278', 'loadClassLoader'));
25
 
26
+ $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
+ call_user_func(\Composer\Autoload\ComposerStaticInitf7070d6c9209c4d83defebc2b9edd278::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
48
  $loader->register(true);
49
 
50
  if ($useStaticLoader) {
51
+ $includeFiles = Composer\Autoload\ComposerStaticInitf7070d6c9209c4d83defebc2b9edd278::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
+ composerRequiref7070d6c9209c4d83defebc2b9edd278($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
+ function composerRequiref7070d6c9209c4d83defebc2b9edd278($fileIdentifier, $file)
64
  {
65
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
  require $file;
vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInitc76a9eae629b371d4ea958147a147184
8
  {
9
  public static $files = array (
10
  '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
@@ -102,25 +102,27 @@ class ComposerStaticInitc76a9eae629b371d4ea958147a147184
102
  'IdiormString' => __DIR__ . '/..' . '/j4mie/idiorm/idiorm.php',
103
  'IdiormStringException' => __DIR__ . '/..' . '/j4mie/idiorm/idiorm.php',
104
  'MailPoet\\API\\API' => __DIR__ . '/../..' . '/lib/API/API.php',
105
- 'MailPoet\\API\\Access' => __DIR__ . '/../..' . '/lib/API/Access.php',
106
- 'MailPoet\\API\\Endpoint' => __DIR__ . '/../..' . '/lib/API/Endpoint.php',
107
- 'MailPoet\\API\\Endpoints\\v1\\AutomatedLatestContent' => __DIR__ . '/../..' . '/lib/API/Endpoints/v1/AutomatedLatestContent.php',
108
- 'MailPoet\\API\\Endpoints\\v1\\CustomFields' => __DIR__ . '/../..' . '/lib/API/Endpoints/v1/CustomFields.php',
109
- 'MailPoet\\API\\Endpoints\\v1\\Forms' => __DIR__ . '/../..' . '/lib/API/Endpoints/v1/Forms.php',
110
- 'MailPoet\\API\\Endpoints\\v1\\ImportExport' => __DIR__ . '/../..' . '/lib/API/Endpoints/v1/ImportExport.php',
111
- 'MailPoet\\API\\Endpoints\\v1\\Mailer' => __DIR__ . '/../..' . '/lib/API/Endpoints/v1/Mailer.php',
112
- 'MailPoet\\API\\Endpoints\\v1\\NewsletterTemplates' => __DIR__ . '/../..' . '/lib/API/Endpoints/v1/NewsletterTemplates.php',
113
- 'MailPoet\\API\\Endpoints\\v1\\Newsletters' => __DIR__ . '/../..' . '/lib/API/Endpoints/v1/Newsletters.php',
114
- 'MailPoet\\API\\Endpoints\\v1\\Segments' => __DIR__ . '/../..' . '/lib/API/Endpoints/v1/Segments.php',
115
- 'MailPoet\\API\\Endpoints\\v1\\SendingQueue' => __DIR__ . '/../..' . '/lib/API/Endpoints/v1/SendingQueue.php',
116
- 'MailPoet\\API\\Endpoints\\v1\\Services' => __DIR__ . '/../..' . '/lib/API/Endpoints/v1/Services.php',
117
- 'MailPoet\\API\\Endpoints\\v1\\Settings' => __DIR__ . '/../..' . '/lib/API/Endpoints/v1/Settings.php',
118
- 'MailPoet\\API\\Endpoints\\v1\\Setup' => __DIR__ . '/../..' . '/lib/API/Endpoints/v1/Setup.php',
119
- 'MailPoet\\API\\Endpoints\\v1\\Subscribers' => __DIR__ . '/../..' . '/lib/API/Endpoints/v1/Subscribers.php',
120
- 'MailPoet\\API\\Error' => __DIR__ . '/../..' . '/lib/API/Error.php',
121
- 'MailPoet\\API\\ErrorResponse' => __DIR__ . '/../..' . '/lib/API/ErrorResponse.php',
122
- 'MailPoet\\API\\Response' => __DIR__ . '/../..' . '/lib/API/Response.php',
123
- 'MailPoet\\API\\SuccessResponse' => __DIR__ . '/../..' . '/lib/API/SuccessResponse.php',
 
 
124
  'MailPoet\\Analytics\\Reporter' => __DIR__ . '/../..' . '/lib/Analytics/Reporter.php',
125
  'MailPoet\\Config\\Activator' => __DIR__ . '/../..' . '/lib/Config/Activator.php',
126
  'MailPoet\\Config\\Analytics' => __DIR__ . '/../..' . '/lib/Config/Analytics.php',
@@ -615,10 +617,10 @@ class ComposerStaticInitc76a9eae629b371d4ea958147a147184
615
  public static function getInitializer(ClassLoader $loader)
616
  {
617
  return \Closure::bind(function () use ($loader) {
618
- $loader->prefixLengthsPsr4 = ComposerStaticInitc76a9eae629b371d4ea958147a147184::$prefixLengthsPsr4;
619
- $loader->prefixDirsPsr4 = ComposerStaticInitc76a9eae629b371d4ea958147a147184::$prefixDirsPsr4;
620
- $loader->prefixesPsr0 = ComposerStaticInitc76a9eae629b371d4ea958147a147184::$prefixesPsr0;
621
- $loader->classMap = ComposerStaticInitc76a9eae629b371d4ea958147a147184::$classMap;
622
 
623
  }, null, ClassLoader::class);
624
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInitf7070d6c9209c4d83defebc2b9edd278
8
  {
9
  public static $files = array (
10
  '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
102
  'IdiormString' => __DIR__ . '/..' . '/j4mie/idiorm/idiorm.php',
103
  'IdiormStringException' => __DIR__ . '/..' . '/j4mie/idiorm/idiorm.php',
104
  'MailPoet\\API\\API' => __DIR__ . '/../..' . '/lib/API/API.php',
105
+ 'MailPoet\\API\\JSON\\API' => __DIR__ . '/../..' . '/lib/API/JSON/API.php',
106
+ 'MailPoet\\API\\JSON\\Access' => __DIR__ . '/../..' . '/lib/API/JSON/Access.php',
107
+ 'MailPoet\\API\\JSON\\Endpoint' => __DIR__ . '/../..' . '/lib/API/JSON/Endpoint.php',
108
+ 'MailPoet\\API\\JSON\\Error' => __DIR__ . '/../..' . '/lib/API/JSON/Error.php',
109
+ 'MailPoet\\API\\JSON\\ErrorResponse' => __DIR__ . '/../..' . '/lib/API/JSON/ErrorResponse.php',
110
+ 'MailPoet\\API\\JSON\\Response' => __DIR__ . '/../..' . '/lib/API/JSON/Response.php',
111
+ 'MailPoet\\API\\JSON\\SuccessResponse' => __DIR__ . '/../..' . '/lib/API/JSON/SuccessResponse.php',
112
+ 'MailPoet\\API\\JSON\\v1\\AutomatedLatestContent' => __DIR__ . '/../..' . '/lib/API/JSON/v1/AutomatedLatestContent.php',
113
+ 'MailPoet\\API\\JSON\\v1\\CustomFields' => __DIR__ . '/../..' . '/lib/API/JSON/v1/CustomFields.php',
114
+ 'MailPoet\\API\\JSON\\v1\\Forms' => __DIR__ . '/../..' . '/lib/API/JSON/v1/Forms.php',
115
+ 'MailPoet\\API\\JSON\\v1\\ImportExport' => __DIR__ . '/../..' . '/lib/API/JSON/v1/ImportExport.php',
116
+ 'MailPoet\\API\\JSON\\v1\\Mailer' => __DIR__ . '/../..' . '/lib/API/JSON/v1/Mailer.php',
117
+ 'MailPoet\\API\\JSON\\v1\\NewsletterTemplates' => __DIR__ . '/../..' . '/lib/API/JSON/v1/NewsletterTemplates.php',
118
+ 'MailPoet\\API\\JSON\\v1\\Newsletters' => __DIR__ . '/../..' . '/lib/API/JSON/v1/Newsletters.php',
119
+ 'MailPoet\\API\\JSON\\v1\\Segments' => __DIR__ . '/../..' . '/lib/API/JSON/v1/Segments.php',
120
+ 'MailPoet\\API\\JSON\\v1\\SendingQueue' => __DIR__ . '/../..' . '/lib/API/JSON/v1/SendingQueue.php',
121
+ 'MailPoet\\API\\JSON\\v1\\Services' => __DIR__ . '/../..' . '/lib/API/JSON/v1/Services.php',
122
+ 'MailPoet\\API\\JSON\\v1\\Settings' => __DIR__ . '/../..' . '/lib/API/JSON/v1/Settings.php',
123
+ 'MailPoet\\API\\JSON\\v1\\Setup' => __DIR__ . '/../..' . '/lib/API/JSON/v1/Setup.php',
124
+ 'MailPoet\\API\\JSON\\v1\\Subscribers' => __DIR__ . '/../..' . '/lib/API/JSON/v1/Subscribers.php',
125
+ 'MailPoet\\API\\MP\\v1\\API' => __DIR__ . '/../..' . '/lib/API/MP/v1/API.php',
126
  'MailPoet\\Analytics\\Reporter' => __DIR__ . '/../..' . '/lib/Analytics/Reporter.php',
127
  'MailPoet\\Config\\Activator' => __DIR__ . '/../..' . '/lib/Config/Activator.php',
128
  'MailPoet\\Config\\Analytics' => __DIR__ . '/../..' . '/lib/Config/Analytics.php',
617
  public static function getInitializer(ClassLoader $loader)
618
  {
619
  return \Closure::bind(function () use ($loader) {
620
+ $loader->prefixLengthsPsr4 = ComposerStaticInitf7070d6c9209c4d83defebc2b9edd278::$prefixLengthsPsr4;
621
+ $loader->prefixDirsPsr4 = ComposerStaticInitf7070d6c9209c4d83defebc2b9edd278::$prefixDirsPsr4;
622
+ $loader->prefixesPsr0 = ComposerStaticInitf7070d6c9209c4d83defebc2b9edd278::$prefixesPsr0;
623
+ $loader->classMap = ComposerStaticInitf7070d6c9209c4d83defebc2b9edd278::$classMap;
624
 
625
  }, null, ClassLoader::class);
626
  }
vendor/composer/installed.json CHANGED
@@ -14,7 +14,7 @@
14
  "reference": "b0c1bda3be5a35da44ba1ac28cc61c67d2ada465",
15
  "shasum": ""
16
  },
17
- "time": "2015-11-28 21:47:43",
18
  "type": "library",
19
  "installation-source": "dist",
20
  "autoload": {
@@ -55,7 +55,7 @@
55
  "require-dev": {
56
  "phpunit/phpunit": "^5.6"
57
  },
58
- "time": "2016-12-14 06:28:26",
59
  "type": "library",
60
  "installation-source": "dist",
61
  "autoload": {
@@ -116,7 +116,7 @@
116
  "j4mie/idiorm": "1.5.*",
117
  "php": ">=5.2.0"
118
  },
119
- "time": "2014-09-23 10:49:36",
120
  "type": "library",
121
  "installation-source": "dist",
122
  "autoload": {
@@ -180,7 +180,7 @@
180
  "require-dev": {
181
  "phpunit/phpunit": "~4.0|~5.0"
182
  },
183
- "time": "2017-01-23 04:29:33",
184
  "type": "library",
185
  "installation-source": "dist",
186
  "autoload": {
@@ -226,7 +226,7 @@
226
  "suggest": {
227
  "ext-mbstring": "For best performance"
228
  },
229
- "time": "2016-11-14 01:06:16",
230
  "type": "library",
231
  "extra": {
232
  "branch-alias": {
@@ -299,7 +299,7 @@
299
  "symfony/config": "",
300
  "symfony/yaml": ""
301
  },
302
- "time": "2017-03-04 12:20:59",
303
  "type": "library",
304
  "extra": {
305
  "branch-alias": {
@@ -355,7 +355,7 @@
355
  "friendsofphp/php-cs-fixer": "~2",
356
  "phpunit/phpunit": "~4.0 || ~5.0"
357
  },
358
- "time": "2017-01-16 07:55:07",
359
  "type": "library",
360
  "extra": {
361
  "branch-alias": {
@@ -408,7 +408,7 @@
408
  "require-dev": {
409
  "phpunit/phpunit": "*"
410
  },
411
- "time": "2016-07-19 19:14:21",
412
  "type": "library",
413
  "installation-source": "dist",
414
  "autoload": {
@@ -457,7 +457,7 @@
457
  "phpunit/phpunit": ">=4.0",
458
  "soundasleep/component-tests": "dev-master"
459
  },
460
- "time": "2016-06-09 04:56:16",
461
  "type": "library",
462
  "installation-source": "dist",
463
  "autoload": {
@@ -509,7 +509,7 @@
509
  "mockery/mockery": "~0.9.1",
510
  "symfony/phpunit-bridge": "~3.2"
511
  },
512
- "time": "2017-02-13 07:52:53",
513
  "type": "library",
514
  "extra": {
515
  "branch-alias": {
@@ -564,7 +564,7 @@
564
  "require-dev": {
565
  "htmlawed/htmlawed": "dev-master"
566
  },
567
- "time": "2016-01-14 20:55:00",
568
  "type": "library",
569
  "installation-source": "dist",
570
  "autoload": {
@@ -620,7 +620,7 @@
620
  "symfony/debug": "~2.7",
621
  "symfony/phpunit-bridge": "~3.2"
622
  },
623
- "time": "2017-02-27 00:07:03",
624
  "type": "library",
625
  "extra": {
626
  "branch-alias": {
14
  "reference": "b0c1bda3be5a35da44ba1ac28cc61c67d2ada465",
15
  "shasum": ""
16
  },
17
+ "time": "2015-11-28T21:47:43+00:00",
18
  "type": "library",
19
  "installation-source": "dist",
20
  "autoload": {
55
  "require-dev": {
56
  "phpunit/phpunit": "^5.6"
57
  },
58
+ "time": "2016-12-14T06:28:26+00:00",
59
  "type": "library",
60
  "installation-source": "dist",
61
  "autoload": {
116
  "j4mie/idiorm": "1.5.*",
117
  "php": ">=5.2.0"
118
  },
119
+ "time": "2014-09-23T10:49:36+00:00",
120
  "type": "library",
121
  "installation-source": "dist",
122
  "autoload": {
180
  "require-dev": {
181
  "phpunit/phpunit": "~4.0|~5.0"
182
  },
183
+ "time": "2017-01-23T04:29:33+00:00",
184
  "type": "library",
185
  "installation-source": "dist",
186
  "autoload": {
226
  "suggest": {
227
  "ext-mbstring": "For best performance"
228
  },
229
+ "time": "2016-11-14T01:06:16+00:00",
230
  "type": "library",
231
  "extra": {
232
  "branch-alias": {
299
  "symfony/config": "",
300
  "symfony/yaml": ""
301
  },
302
+ "time": "2017-03-04T12:20:59+00:00",
303
  "type": "library",
304
  "extra": {
305
  "branch-alias": {
355
  "friendsofphp/php-cs-fixer": "~2",
356
  "phpunit/phpunit": "~4.0 || ~5.0"
357
  },
358
+ "time": "2017-01-16T07:55:07+00:00",
359
  "type": "library",
360
  "extra": {
361
  "branch-alias": {
408
  "require-dev": {
409
  "phpunit/phpunit": "*"
410
  },
411
+ "time": "2016-07-19T19:14:21+00:00",
412
  "type": "library",
413
  "installation-source": "dist",
414
  "autoload": {
457
  "phpunit/phpunit": ">=4.0",
458
  "soundasleep/component-tests": "dev-master"
459
  },
460
+ "time": "2016-06-09T04:56:16+00:00",
461
  "type": "library",
462
  "installation-source": "dist",
463
  "autoload": {
509
  "mockery/mockery": "~0.9.1",
510
  "symfony/phpunit-bridge": "~3.2"
511
  },
512
+ "time": "2017-02-13T07:52:53+00:00",
513
  "type": "library",
514
  "extra": {
515
  "branch-alias": {
564
  "require-dev": {
565
  "htmlawed/htmlawed": "dev-master"
566
  },
567
+ "time": "2016-01-14T20:55:00+00:00",
568
  "type": "library",
569
  "installation-source": "dist",
570
  "autoload": {
620
  "symfony/debug": "~2.7",
621
  "symfony/phpunit-bridge": "~3.2"
622
  },
623
+ "time": "2017-02-27T00:07:03+00:00",
624
  "type": "library",
625
  "extra": {
626
  "branch-alias": {