├── .gitignore ├── .php_cs.dist ├── assets ├── css │ └── pastie.css ├── images │ └── mj-example-heroimage.png └── js │ └── rainbow-custom.min.js ├── blueprints ├── fields │ ├── mj-example-block-footer.yml │ ├── mj-example-block-headline.yml │ ├── mj-example-block-hero.yml │ ├── mj-example-block-news.yml │ ├── mj-example-block-text.yml │ ├── mj-example-contactslists.yml │ ├── mj-example-email.yml │ ├── mj-example-hash.yml │ ├── mj-example-links.yml │ ├── mj-example-newsletter.yml │ ├── mj-example-preview.yml │ ├── mj-example-save-reminder.yml │ ├── mj-example-schedule-date.yml │ ├── mj-example-schedule-time.yml │ ├── mj-example-segment.yml │ ├── mj-example-senders.yml │ ├── mj-example-test.yml │ └── mj-example-trans.yml └── mj-example.yml ├── composer.json ├── composer.lock ├── controllers └── mj-example.php ├── example.md ├── fields ├── kirbymailjethash │ └── kirbymailjethash.php └── messagebox │ └── messagebox.php ├── kirby-mailjet-class.php ├── kirby-mailjet-emailservice.php ├── kirby-mailjet-examples.php ├── kirby-mailjet-routes.php ├── kirby-mailjet.php ├── languages ├── de.php └── en.php ├── license.md ├── package.json ├── readme.md ├── snippets ├── mj-example-block-footer.html ├── mj-example-block-footer.php ├── mj-example-block-head.php ├── mj-example-block-headline.html ├── mj-example-block-headline.php ├── mj-example-block-hero.html ├── mj-example-block-hero.php ├── mj-example-block-news.html ├── mj-example-block-news.php ├── mj-example-block-text.html ├── mj-example-block-text.php ├── mj-example-email.html ├── mj-example-email.mjml ├── mj-example-email.php ├── mj-example-form-error.php ├── mj-example-newsletter.html ├── mj-example-newsletter.mjml └── mj-example-newsletter.php ├── templates └── mj-example.php ├── vendor ├── autoload.php ├── composer │ ├── ClassLoader.php │ ├── autoload_classmap.php │ ├── autoload_files.php │ ├── autoload_namespaces.php │ ├── autoload_psr4.php │ ├── autoload_real.php │ └── autoload_static.php ├── guzzlehttp │ ├── guzzle │ │ └── src │ │ │ ├── Client.php │ │ │ ├── ClientInterface.php │ │ │ ├── Cookie │ │ │ ├── CookieJar.php │ │ │ ├── CookieJarInterface.php │ │ │ ├── FileCookieJar.php │ │ │ ├── SessionCookieJar.php │ │ │ └── SetCookie.php │ │ │ ├── Exception │ │ │ ├── BadResponseException.php │ │ │ ├── ClientException.php │ │ │ ├── ConnectException.php │ │ │ ├── GuzzleException.php │ │ │ ├── RequestException.php │ │ │ ├── SeekException.php │ │ │ ├── ServerException.php │ │ │ ├── TooManyRedirectsException.php │ │ │ └── TransferException.php │ │ │ ├── Handler │ │ │ ├── CurlFactory.php │ │ │ ├── CurlFactoryInterface.php │ │ │ ├── CurlHandler.php │ │ │ ├── CurlMultiHandler.php │ │ │ ├── EasyHandle.php │ │ │ ├── MockHandler.php │ │ │ ├── Proxy.php │ │ │ └── StreamHandler.php │ │ │ ├── HandlerStack.php │ │ │ ├── MessageFormatter.php │ │ │ ├── Middleware.php │ │ │ ├── Pool.php │ │ │ ├── PrepareBodyMiddleware.php │ │ │ ├── RedirectMiddleware.php │ │ │ ├── RequestOptions.php │ │ │ ├── RetryMiddleware.php │ │ │ ├── TransferStats.php │ │ │ ├── UriTemplate.php │ │ │ ├── functions.php │ │ │ └── functions_include.php │ ├── promises │ │ ├── Makefile │ │ └── src │ │ │ ├── AggregateException.php │ │ │ ├── CancellationException.php │ │ │ ├── Coroutine.php │ │ │ ├── EachPromise.php │ │ │ ├── FulfilledPromise.php │ │ │ ├── Promise.php │ │ │ ├── PromiseInterface.php │ │ │ ├── PromisorInterface.php │ │ │ ├── RejectedPromise.php │ │ │ ├── RejectionException.php │ │ │ ├── TaskQueue.php │ │ │ ├── TaskQueueInterface.php │ │ │ ├── functions.php │ │ │ └── functions_include.php │ └── psr7 │ │ └── src │ │ ├── AppendStream.php │ │ ├── BufferStream.php │ │ ├── CachingStream.php │ │ ├── DroppingStream.php │ │ ├── FnStream.php │ │ ├── InflateStream.php │ │ ├── LazyOpenStream.php │ │ ├── LimitStream.php │ │ ├── MessageTrait.php │ │ ├── MultipartStream.php │ │ ├── NoSeekStream.php │ │ ├── PumpStream.php │ │ ├── Request.php │ │ ├── Response.php │ │ ├── Rfc7230.php │ │ ├── ServerRequest.php │ │ ├── Stream.php │ │ ├── StreamDecoratorTrait.php │ │ ├── StreamWrapper.php │ │ ├── UploadedFile.php │ │ ├── Uri.php │ │ ├── UriNormalizer.php │ │ ├── UriResolver.php │ │ ├── functions.php │ │ └── functions_include.php ├── mailjet │ └── mailjet-apiv3-php │ │ └── src │ │ └── Mailjet │ │ ├── Client.php │ │ ├── Config.php │ │ ├── Request.php │ │ ├── Resources.php │ │ └── Response.php ├── mustache │ └── mustache │ │ ├── bin │ │ └── build_bootstrap.php │ │ └── src │ │ └── Mustache │ │ ├── Autoloader.php │ │ ├── Cache.php │ │ ├── Cache │ │ ├── AbstractCache.php │ │ ├── FilesystemCache.php │ │ └── NoopCache.php │ │ ├── Compiler.php │ │ ├── Context.php │ │ ├── Engine.php │ │ ├── Exception.php │ │ ├── Exception │ │ ├── InvalidArgumentException.php │ │ ├── LogicException.php │ │ ├── RuntimeException.php │ │ ├── SyntaxException.php │ │ ├── UnknownFilterException.php │ │ ├── UnknownHelperException.php │ │ └── UnknownTemplateException.php │ │ ├── HelperCollection.php │ │ ├── LambdaHelper.php │ │ ├── Loader.php │ │ ├── Loader │ │ ├── ArrayLoader.php │ │ ├── CascadingLoader.php │ │ ├── FilesystemLoader.php │ │ ├── InlineLoader.php │ │ ├── MutableLoader.php │ │ ├── ProductionFilesystemLoader.php │ │ └── StringLoader.php │ │ ├── Logger.php │ │ ├── Logger │ │ ├── AbstractLogger.php │ │ └── StreamLogger.php │ │ ├── Parser.php │ │ ├── Source.php │ │ ├── Source │ │ └── FilesystemSource.php │ │ ├── Template.php │ │ └── Tokenizer.php ├── psr │ └── http-message │ │ └── src │ │ ├── MessageInterface.php │ │ ├── RequestInterface.php │ │ ├── ResponseInterface.php │ │ ├── ServerRequestInterface.php │ │ ├── StreamInterface.php │ │ ├── UploadedFileInterface.php │ │ └── UriInterface.php └── ralouphie │ └── getallheaders │ └── src │ └── getallheaders.php └── widgets └── mailjet ├── mailjet.html.php └── mailjet.php /.gitignore: -------------------------------------------------------------------------------- 1 | # OS files 2 | .DS_Store 3 | .php_cs.cache 4 | 5 | /node_modules 6 | 7 | # files of Composer dependencies that are not needed for the plugin 8 | /vendor/**/.* 9 | /vendor/**/*.json 10 | /vendor/**/*.txt 11 | /vendor/**/*.md 12 | /vendor/**/*.yml 13 | /vendor/**/*.yaml 14 | /vendor/**/*.xml 15 | /vendor/**/*.dist 16 | /vendor/**/readme.php 17 | /vendor/**/LICENSE 18 | /vendor/**/COPYING 19 | /vendor/**/VERSION 20 | /vendor/**/docs/* 21 | /vendor/**/example/* 22 | /vendor/**/examples/* 23 | /vendor/**/test/* 24 | /vendor/**/tests/* 25 | /vendor/**/php4/* 26 | /vendor/getkirby/composer-installer -------------------------------------------------------------------------------- /.php_cs.dist: -------------------------------------------------------------------------------- 1 | exclude('vendor') 5 | ->exclude('node_modules') 6 | ->exclude('src') 7 | ->exclude('kirby') 8 | ->exclude('templates') 9 | ->exclude('widgets') 10 | ->in(__DIR__) 11 | ; 12 | 13 | return PhpCsFixer\Config::create() 14 | ->setRules([ 15 | '@PSR2' => true, 16 | ]) 17 | ->setFinder($finder) 18 | ; -------------------------------------------------------------------------------- /assets/css/pastie.css: -------------------------------------------------------------------------------- 1 | @keyframes fade-in{0%{opacity:0}100%{opacity:1}}@keyframes fade{10%{transform:scale(1, 1)}35%{transform:scale(1, 1.7)}40%{transform:scale(1, 1.7)}50%{opacity:1}60%{transform:scale(1, 1)}100%{transform:scale(1, 1);opacity:0}}[data-language] code,[class^="lang"] code,pre [data-language],pre [class^="lang"]{opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";animation:50ms ease-in-out 2s forwards fade-in}[data-language] code.rainbow,[class^="lang"] code.rainbow,pre [data-language].rainbow,pre [class^="lang"].rainbow{animation-delay:0s}[data-language] code.loading,[class^="lang"] code.loading,pre [data-language].loading,pre [class^="lang"].loading{animation-play-state:paused}pre{position:relative}pre.loading .preloader div{animation-play-state:running}pre.loading .preloader div:nth-of-type(1){background:#0081f5;animation:fade 1.5s 300ms linear infinite}pre.loading .preloader div:nth-of-type(2){background:#5000f5;animation:fade 1.5s 438ms linear infinite}pre.loading .preloader div:nth-of-type(3){background:#9000f5;animation:fade 1.5s 577ms linear infinite}pre.loading .preloader div:nth-of-type(4){background:#f50419;animation:fade 1.5s 715ms linear infinite}pre.loading .preloader div:nth-of-type(5){background:#f57900;animation:fade 1.5s 853ms linear infinite}pre.loading .preloader div:nth-of-type(6){background:#f5e600;animation:fade 1.5s 992ms linear infinite}pre.loading .preloader div:nth-of-type(7){background:#00f50c;animation:fade 1.5s 1130ms linear infinite}pre .preloader{position:absolute;top:12px;left:10px}pre .preloader div{width:12px;height:12px;border-radius:4px;display:inline-block;margin-right:4px;opacity:0;animation-play-state:paused;animation-fill-mode:forwards}pre{background-color:#000;word-wrap:break-word;margin:0px;padding:10px;color:#fff;font-size:14px;margin-bottom:20px}pre,code{font-family:'Monaco', 'Menlo', courier, monospace}pre{background-color:#F8F8FF;border:1px solid #DEDEDE;color:#000;font-size:13px;line-height:16px}pre,code{font-family:monospace}pre .comment,code .comment{color:#888}pre .keyword,pre .selector,pre .storage.module,pre .storage.class,pre .storage.function,code .keyword,code .selector,code .storage.module,code .storage.class,code .storage.function{color:#080;font-weight:bold}pre .keyword.operator,code .keyword.operator{color:#000;font-weight:normal}pre .constant.language,code .constant.language{color:#038;font-weight:bold}pre .constant.symbol,pre .class,pre .constant,code .constant.symbol,code .class,code .constant{color:#036;font-weight:bold}pre .keyword.namespace,pre .entity.name.class,code .keyword.namespace,code .entity.name.class{color:#B06;font-weight:bold}pre .constant.numeric,code .constant.numeric{color:#00D;font-weight:bold}pre .string,pre .comment.docstring,code .string,code .comment.docstring{color:#D20;background-color:#FFF0F0}pre .string.regexp,code .string.regexp{background-color:#FFF0FF;color:#808}pre .variable.instance,code .variable.instance{color:#33B}pre .entity.name.function,code .entity.name.function{color:#06B;font-weight:bold}pre .support.tag-name,pre .entity.tag.script,pre .entity.tag.style,code .support.tag-name,code .entity.tag.script,code .entity.tag.style{color:#070}pre .support.attribute,code .support.attribute{color:#007;font-style:italic}pre .entity.name.tag,pre .storage.type,code .entity.name.tag,code .storage.type{color:#070;font-weight:bold}pre .variable.self,pre .support.function,code .variable.self,code .support.function{color:#038;font-weight:bold}pre .entity.function,pre .support.magic,pre.support.method,code .entity.function,code .support.magic,code.support.method{color:#C00;font-weight:bold} -------------------------------------------------------------------------------- /assets/images/mj-example-heroimage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnomei/kirby-mailjet/6a1049b53de37dcec5cb86895b320ebd2d91df40/assets/images/mj-example-heroimage.png -------------------------------------------------------------------------------- /blueprints/fields/mj-example-block-footer.yml: -------------------------------------------------------------------------------- 1 | # 2 | # footer 3 | # 4 | label: mj-example-block-footer 5 | snippet: mj-example-block-footer 6 | fields: 7 | text: 8 | label: text 9 | type: textarea 10 | label: text 11 | facebook: 12 | type: url 13 | icon: facebook 14 | googleplus: 15 | type: url 16 | icon: google -------------------------------------------------------------------------------- /blueprints/fields/mj-example-block-headline.yml: -------------------------------------------------------------------------------- 1 | # 2 | # headline 3 | # 4 | label: mj-example-block-headline 5 | snippet: mj-example-block-headline 6 | fields: 7 | headline: 8 | type: text 9 | label: headline -------------------------------------------------------------------------------- /blueprints/fields/mj-example-block-hero.yml: -------------------------------------------------------------------------------- 1 | # 2 | # hero 3 | # 4 | label: mj-example-block-hero 5 | snippet: mj-example-block-hero 6 | fields: 7 | heroheadline: 8 | type: text 9 | label: heroheadline 10 | herobutton: 11 | type: text 12 | label: herobutton 13 | herolink: 14 | type: text # using type 'text' not 'url' to support url()-helper 15 | label: herolink 16 | heroimage: 17 | type: text # using type 'text' not 'url' to support url()-helper 18 | label: heroimage -------------------------------------------------------------------------------- /blueprints/fields/mj-example-block-news.yml: -------------------------------------------------------------------------------- 1 | # 2 | # news 3 | # 4 | label: mj-example-block-news 5 | snippet: mj-example-block-news 6 | fields: 7 | newsheadline: 8 | type: text 9 | label: newsheadline -------------------------------------------------------------------------------- /blueprints/fields/mj-example-block-text.yml: -------------------------------------------------------------------------------- 1 | # 2 | # text 3 | # 4 | label: mj-example-block-text 5 | snippet: mj-example-block-text 6 | fields: 7 | text: 8 | type: textarea 9 | label: text -------------------------------------------------------------------------------- /blueprints/fields/mj-example-contactslists.yml: -------------------------------------------------------------------------------- 1 | # global def 2 | label: Contactslists 3 | type: select 4 | width: 1/2 5 | # URL to route needs to be hardcoded if you use kirby version < 2.4.2 6 | # https://github.com/getkirby/panel/issues/1035 7 | options: http://YOUR_DOMAIN_HERE/kirby-mailjet/PLUGIN_HASH_HERE/json/contactslists.json 8 | # since kirby version 2.4.2 9 | #options: url 10 | #url: kirby-mailjet/PLUGIN_HASH_HERE/json/contactslists.json -------------------------------------------------------------------------------- /blueprints/fields/mj-example-email.yml: -------------------------------------------------------------------------------- 1 | # global def 2 | label: Email for Test 3 | type: email 4 | placeholder: "send to me" 5 | #width: 1/2 6 | #help: Erst Speichern dann senden! Wenn leer gehts an einen selbst. -------------------------------------------------------------------------------- /blueprints/fields/mj-example-hash.yml: -------------------------------------------------------------------------------- 1 | label: 'Hash' 2 | type: kirbymailjethash 3 | -------------------------------------------------------------------------------- /blueprints/fields/mj-example-links.yml: -------------------------------------------------------------------------------- 1 | #global def 2 | #label: 'Links' 3 | type: info 4 | text: > 5 | Dashboard 6 | Campaigns 7 | Contactslists 8 | Segmentation 9 | -------------------------------------------------------------------------------- /blueprints/fields/mj-example-newsletter.yml: -------------------------------------------------------------------------------- 1 | #global def 2 | label: ' ' 3 | type: opener 4 | width: 1/2 5 | command: '{page.url}/mailjet:send/{page.secret}' 6 | text: "Send Newsletter to Contactslist and apply Segment (if any)" 7 | textprogress: "Send Newsletter to Contactslist and apply Segment (if any)" 8 | textsuccess: "Sent Newsletter!" 9 | #texterror: "Not possible!" 10 | confirm: 'Publish now?' -------------------------------------------------------------------------------- /blueprints/fields/mj-example-preview.yml: -------------------------------------------------------------------------------- 1 | #global def 2 | label: 'E-Mail' 3 | type: opener 4 | width: 1/2 5 | command: '{page.url}/mailjet:test/mode:preview/{page.secret}/open:yes' 6 | text: "Preview E-Mail online" 7 | -------------------------------------------------------------------------------- /blueprints/fields/mj-example-save-reminder.yml: -------------------------------------------------------------------------------- 1 | label: ' ' 2 | type: messagebox 3 | text: "Save before sending E-Mails" 4 | color: "#d31f26" 5 | bordercolor: "#d31f26" -------------------------------------------------------------------------------- /blueprints/fields/mj-example-schedule-date.yml: -------------------------------------------------------------------------------- 1 | label: Schedule Date UTC 2 | type: date 3 | #default: today 4 | width: 1/2 5 | format: YYYY-MM-DD 6 | -------------------------------------------------------------------------------- /blueprints/fields/mj-example-schedule-time.yml: -------------------------------------------------------------------------------- 1 | label: Schedule Time UTC 2 | type: time 3 | #default: now 4 | width: 1/2 5 | help: Current Time at UTC -------------------------------------------------------------------------------- /blueprints/fields/mj-example-segment.yml: -------------------------------------------------------------------------------- 1 | # global def 2 | label: Segment 3 | type: select 4 | width: 1/2 5 | # URL to route needs to be hardcoded if you use kirby version < 2.4.2 6 | # https://github.com/getkirby/panel/issues/1035 7 | options: http://YOUR_DOMAIN_HERE/kirby-mailjet/PLUGIN_HASH_HERE/json/segments.json 8 | # since kirby version 2.4.2 9 | #options: url 10 | #url: kirby-mailjet/PLUGIN_HASH_HERE/json/segments.json -------------------------------------------------------------------------------- /blueprints/fields/mj-example-senders.yml: -------------------------------------------------------------------------------- 1 | # global def 2 | label: Sender 3 | type: select 4 | width: 1/1 5 | # URL to route needs to be hardcoded if you use kirby version < 2.4.2 6 | # https://github.com/getkirby/panel/issues/1035 7 | options: http://YOUR_DOMAIN_HERE/kirby-mailjet/PLUGIN_HASH_HERE/json/senders.json 8 | # since kirby version 2.4.2 9 | #options: url 10 | #url: kirby-mailjet/PLUGIN_HASH_HERE/json/senders.json 11 | -------------------------------------------------------------------------------- /blueprints/fields/mj-example-test.yml: -------------------------------------------------------------------------------- 1 | #global def 2 | label: 'Newsletter' 3 | type: opener 4 | width: 1/2 5 | command: '{page.url}/mailjet:test/{page.secret}' 6 | text: "Send Newsletter TEST to email-adress above" 7 | textprogress: "Send Newsletter TEST to email above" 8 | textsuccess: "Newsletter TEST Sent!" 9 | #texterror: "Not possible!" -------------------------------------------------------------------------------- /blueprints/fields/mj-example-trans.yml: -------------------------------------------------------------------------------- 1 | #global def 2 | label: ' ' 3 | type: opener 4 | width: 1/2 5 | command: '{page.url}/mailjet:test/mode:transactional/{page.secret}' 6 | text: "Send to email above (transactional)" 7 | textprogress: "Send to email above (transactional)" 8 | textsuccess: "Sent (transactional)!" 9 | #texterror: "Not possible!" -------------------------------------------------------------------------------- /blueprints/mj-example.yml: -------------------------------------------------------------------------------- 1 | title: Mailjet Plugin Example Page 2 | icon: life-ring 3 | options: 4 | status: false 5 | template: false 6 | url: false 7 | fields: 8 | title: 9 | type: text 10 | default: mailjetexample 11 | readonly: true 12 | icon: life-ring 13 | help: > 14 | 15 | docsmailjet: 16 | type: opener 17 | command: 'https://github.com/bnomei/kirby-mailjet/open:yes' 18 | text: 'Mailjet Plugin Github Docs' 19 | width: 1/2 20 | docsopener: 21 | type: opener 22 | command: 'https://github.com/bnomei/kirby-opener/open:yes' 23 | text: 'Opener Plugin Github Docs' 24 | width: 1/2 25 | 26 | #-------------------------------------- 27 | builder-line: 28 | type: headline 29 | label: Kirby Builder 30 | 31 | builder: 32 | type: builder 33 | fieldsets: 34 | # use 'extends'. see https://github.com/TimOetting/kirby-builder/issues/8 35 | headline: 36 | extends: mj-example-block-headline 37 | text: 38 | extends: mj-example-block-text 39 | hero: 40 | extends: mj-example-block-hero 41 | news: 42 | extends: mj-example-block-news 43 | footer: 44 | extends: mj-example-block-footer 45 | help: "With kirby-mailjet each fieldset should be used only once!" 46 | 47 | #-------------------------------------- 48 | mailjet-line: 49 | type: headline 50 | label: Kirby Mailjet 51 | 52 | mjhash: mj-example-hash 53 | mjcontactslist: mj-example-contactslists 54 | mjsegment: mj-example-segment 55 | mjemail: mj-example-email 56 | mjscheduledate: mj-schedule-date 57 | mjscheduletime: mj-schedule-time 58 | mjsenders: mj-senders 59 | mjreminder: mj-example-save-reminder 60 | mjpreview: mj-example-preview 61 | mjtrans: mj-example-trans 62 | mjtest: mj-example-test 63 | mjpublish: mj-example-newsletter 64 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "mailjet/mailjet-apiv3-php": "~1.1", 4 | "mustache/mustache": "~2.11" 5 | }, 6 | "config": { 7 | "optimize-autoloader": true, 8 | "sort-packages": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /fields/kirbymailjethash/kirbymailjethash.php: -------------------------------------------------------------------------------- 1 | padding) ? $this->padding : '10px'; 10 | $textalign = isset($this->align) ? $this->align : 'center'; 11 | $color = isset($this->color) ? $this->color : '#888'; 12 | $borderwidth = '2px'; 13 | $borderstyle = 'solid'; 14 | $borderradius = '0px'; 15 | $bordercolor = isset($this->bordercolor) ? $this->bordercolor : '#ddd'; 16 | $backgroundcolor = isset($this->backgroundcolor) ? $this->backgroundcolor : 'transparent'; 17 | 18 | $reminder = new Brick('div', KirbyMailjet::hash()); 19 | $reminder->attr('style', "width:100%;text-align:$textalign;font-weight:$fontwidth;font-style:$fontstyle;color:$color;background-color:$backgroundcolor;border:$borderwidth $borderstyle $bordercolor;padding:$padding;border-radius:$borderradius;"); 20 | 21 | return $reminder; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /fields/messagebox/messagebox.php: -------------------------------------------------------------------------------- 1 | padding) ? $this->padding : '10px'; 10 | $textalign = isset($this->align) ? $this->align : 'center'; 11 | $color = isset($this->color) ? $this->color : '#000'; 12 | $borderwidth = '2px'; 13 | $borderstyle = 'solid'; 14 | $borderradius = '0px'; 15 | $bordercolor = isset($this->bordercolor) ? $this->bordercolor : '#000'; 16 | $backgroundcolor = isset($this->backgroundcolor) ? $this->backgroundcolor : 'transparent'; 17 | 18 | $reminder = new Brick('div', $this->text); 19 | $reminder->attr('style', "width:100%;text-align:$textalign;font-weight:$fontwidth;font-style:$fontstyle;color:$color;background-color:$backgroundcolor;border:$borderwidth $borderstyle $bordercolor;padding:$padding;border-radius:$borderradius;"); 20 | 21 | return $reminder; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /kirby-mailjet-emailservice.php: -------------------------------------------------------------------------------- 1 | 'POST', 14 | 'FromEmail' => KirbyMailjet::senderAdress($email->from), // verified sender of domain 15 | 'FromName' => KirbyMailjet::senderName(), 16 | 'Subject' => str::utf8($email->subject), 17 | 'Html-part' => str::utf8($email->body), 18 | 'Recipients' => [['Email' => $email->to]], 19 | ]; 20 | 21 | if ($textpart = a::get($email->options, 'Text-part')) { 22 | $body['Text-part'] = str::utf8($textpart); 23 | } 24 | 25 | if ($mjcampaign = a::get($email->options, 'Mj-campaign')) { 26 | $body['Mj-campaign'] = str::utf8($mjcampaign); 27 | } 28 | 29 | if ($attachments = a::get($email->options, 'Attachments')) { 30 | if (is_array($attachments) && count($attachments) > 0) { 31 | $allValid = true; 32 | foreach ($attachments as $at) { 33 | $missing = a::missing($at, ['Content-type', 'Filename', 'content']); 34 | if (count($missing) > 0) { 35 | $allValid = false; 36 | break; 37 | } 38 | } 39 | if ($allValid) { 40 | $body['Attachments'] = $attachments; 41 | } 42 | } 43 | } 44 | 45 | $response = $mj->post(Resources::$Email, ['body' => $body]); 46 | if ($response->success()) { 47 | $send = true; 48 | } else { 49 | $error = KirbyMailjet::getResponseError($response); 50 | } 51 | } 52 | 53 | if (!$send) { 54 | throw new Error($error); 55 | } 56 | }; 57 | 58 | email::$services[KirbyMailjet::PHPMAIL_SERVICE] = function ($email) { 59 | $headers = array( 60 | 'From: ' . $email->from, 61 | 'Reply-To: ' . $email->replyTo, 62 | 'Return-Path: ' . $email->replyTo, 63 | 'Message-ID: <' . time() . '-' . $email->from . '>', 64 | 'X-Mailer: PHP v' . phpversion(), 65 | 'Content-Type: text/html; charset=utf-8', 66 | 'Content-Transfer-Encoding: 8bit', 67 | ); 68 | if (a::get($email->options, 'bcc') && v::email($email->options['bcc'])) { // add bcc 69 | array_push($headers, 'Bcc: ' . $email->options['bcc']); 70 | } 71 | 72 | ini_set('sendmail_from', $email->from); 73 | $send = mail($email->to, str::utf8($email->subject), str::utf8($email->body), implode(PHP_EOL, $headers)); 74 | ini_restore('sendmail_from'); 75 | 76 | if (!$send) { 77 | throw new Error('The email could not be sent'); 78 | } 79 | }; 80 | -------------------------------------------------------------------------------- /kirby-mailjet-examples.php: -------------------------------------------------------------------------------- 1 | children() as $folder) { 9 | $folderFiles = new Folder($folder->root()); 10 | foreach ($folderFiles->files() as $file) { 11 | // field root 12 | if ($file->extension() == 'php') { 13 | $kirby->set('field', $file->name(), $file->dir()); 14 | } 15 | } 16 | } 17 | 18 | /**************************************** 19 | BLUEPRINTS 20 | ***************************************/ 21 | 22 | $blueprints = new Folder(__DIR__ . DS . 'blueprints'); 23 | foreach ($blueprints->files() as $file) { 24 | $kirby->set('blueprint', $file->name(), $file->root()); 25 | } 26 | /* manual file copy by user is better since examples disabled on production servers anyway. 27 | */ 28 | /* 29 | $blueprintsFields = new Folder(__DIR__ . DS . 'blueprints' . DS . 'fields'); 30 | foreach ($blueprintsFields->files() as $file) { 31 | $kirby->set('blueprint', 'fields/'.$file->name(), $file->root()); 32 | }*/ 33 | 34 | 35 | /**************************************** 36 | SNIPPETS 37 | ***************************************/ 38 | 39 | /* manual file copy by user is better since examples disabled on production servers anyway. 40 | */ 41 | /* 42 | $snippets = new Folder(__DIR__ . DS . 'snippets'); 43 | foreach ($snippets->files() as $file) { 44 | if($file->extension() == 'php') { 45 | $kirby->set('snippet', $file->name(), $file->root()); 46 | } 47 | } 48 | // https://github.com/TimOetting/kirby-builder/blob/master/builder.php#L43 49 | if(c::get('plugin.mailjet.buildersnippets', false)) { 50 | c::set('buildersnippets.path', __DIR__ . DS . 'snippets'); 51 | } 52 | */ 53 | 54 | /**************************************** 55 | TEMPLATES and CONTROLLERS 56 | ***************************************/ 57 | 58 | $kirby->set('controller', 'mj-example', __DIR__ . DS . 'controllers' . DS . 'mj-example.php'); 59 | $kirby->set('template', 'mj-example', __DIR__ . DS . 'templates' . DS . 'mj-example.php'); 60 | 61 | 62 | /**************************************** 63 | HOOKS 64 | ***************************************/ 65 | 66 | $kirby->set('hook', 'panel.page.create', function ($page) { 67 | if ($page->template() == 'mj-example') { 68 | try { 69 | $builder = [ 70 | [ 71 | 'headline' => 'Responsive Email Builder', 72 | '_fieldset' => 'headline', 73 | ], 74 | [ 75 | 'text' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam posuere, orci in **tristique consectetur**, quam lacus pulvinar ex, quis facilisis nibh velit *non magna*. In imperdiet est sit amet tincidunt pellentesque.', 76 | '_fieldset' => 'text', 77 | ], 78 | [ 79 | 'heroheadline' => 'Kirby Mailjet Plugin', 80 | 'herobutton' => 'Buy a license', 81 | 'herolink' => 'https://bnomei.onfastspring.com/kirby-mailjet', 82 | 'heroimage' => 'https://github.com/bnomei/kirby-mailjet/assets/images/mj-example-heroimage.png?raw=true', 83 | '_fieldset' => 'hero', 84 | ], 85 | [ 86 | 'newsheadline' => 'News', 87 | '_fieldset' => 'news' 88 | ], 89 | [ 90 | 'text' => 'Sed ante turpis, feugiat ac tellus ac, cursus molestie tellus. Sed sem est, malesuada in dignissim vitae, porta ut magna.', 91 | 'facebook' => "", 92 | 'googleplus' => "", 93 | '_fieldset' => 'footer', 94 | ], 95 | ]; 96 | $page->update([ 97 | 'title' => 'Mailjet Plugin Example Page', 98 | 'builder' => yaml::encode($builder), 99 | ]); 100 | 101 | $subpages = [ 102 | [ 103 | 'title' => 'Adipiscing', 104 | 'text' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 105 | ], 106 | [ 107 | 'title' => 'Facilisis', 108 | 'text' => 'Nam posuere, orci in tristique consectetur, quam lacus pulvinar ex, quis facilisis nibh velit non magna.', 109 | ], 110 | [ 111 | 'title' => 'Tincidunt', 112 | 'text' => 'In imperdiet est sit amet tincidunt pellentesque.', 113 | ], 114 | ]; 115 | foreach ($subpages as $subpage) { 116 | $page->create( 117 | $page->diruri().'/'.str::slug($subpage['title']), 118 | 'default', 119 | $subpage 120 | ); 121 | } 122 | } catch (Exception $ex) { 123 | // echo $ex->getMessage(); 124 | } 125 | } 126 | }); 127 | -------------------------------------------------------------------------------- /kirby-mailjet-routes.php: -------------------------------------------------------------------------------- 1 | set( 12 | 'route', 13 | array( 14 | 'pattern' => 'kirby-mailjet/(:any)/mjml/(:any)', 15 | 'action' => function ($hash, $snippet) { 16 | $json = array(); 17 | $code = 400; 18 | 19 | // site()->user() // does not work with panel select field 20 | if ($hash == KirbyMailjet::hash()) { 21 | KirbyMailjet::buildMJML($snippet); 22 | KirbyMailjet::execMJML($snippet); 23 | $code = 200; 24 | } 25 | 26 | return response::json($json, $code); 27 | }, 28 | 29 | ) 30 | ); 31 | 32 | $kirby->set( 33 | 'route', 34 | array( 35 | 'pattern' => 'kirby-mailjet/(:any)/json/(:any)', 36 | 'action' => function ($hash, $file) { 37 | $json = array(); 38 | $code = 400; 39 | 40 | // site()->user() // does not work with panel select field 41 | if ($hash == KirbyMailjet::hash()) { 42 | $cl = null; 43 | $cacheFile = kirby()->roots->cache() . DS . $file; 44 | if ($cache = f::read($cacheFile)) { 45 | $cl = json_decode($cache, true); 46 | } 47 | 48 | if ($file == 'contactslists.json') { 49 | if (!$cl || f::modified($cacheFile) + c::get('plugin.mailjet.json.cache', 60 * 5) < time()) { 50 | $cls = KirbyMailjet::contactslists(); 51 | if (count($cls) > 0) { 52 | f::write($cacheFile, json_encode($cls)); 53 | $cl = $cls; 54 | } 55 | } 56 | if ($cl) { 57 | $json = $cl; 58 | $code = 200; 59 | } 60 | } elseif ($file == 'segments.json') { 61 | if (!$cl || f::modified($cacheFile) + c::get('plugin.mailjet.json.cache', 60 * 5) < time()) { 62 | $cls = KirbyMailjet::segments(); 63 | if (count($cls) > 0) { 64 | f::write($cacheFile, json_encode($cls)); 65 | $cl = $cls; 66 | } 67 | } 68 | if ($cl) { 69 | $json = $cl; 70 | $code = 200; 71 | } 72 | } elseif ($file == 'senders.json') { 73 | if (!$cl || f::modified($cacheFile) + c::get('plugin.mailjet.json.cache', 60 * 5) < time()) { 74 | $cls = KirbyMailjet::senders(); 75 | if (count($cls) > 0) { 76 | f::write($cacheFile, json_encode($cls)); 77 | $cl = $cls; 78 | } 79 | } 80 | if ($cl) { 81 | $json = $cl; 82 | $code = 200; 83 | } 84 | } 85 | } 86 | 87 | return response::json($json, $code); 88 | }, 89 | 90 | ) 91 | ); 92 | -------------------------------------------------------------------------------- /kirby-mailjet.php: -------------------------------------------------------------------------------- 1 | plugin('kirby-opener'); 11 | $loadedUniform = kirby()->plugin('uniform'); 12 | } 13 | 14 | require_once __DIR__ . '/kirby-mailjet-class.php'; 15 | require_once __DIR__ . '/kirby-mailjet-emailservice.php'; 16 | require_once __DIR__ . '/kirby-mailjet-routes.php'; 17 | 18 | if (c::get('plugin.mailjet.examples', true)) { 19 | require_once __DIR__ . '/kirby-mailjet-examples.php'; 20 | } 21 | -------------------------------------------------------------------------------- /languages/de.php: -------------------------------------------------------------------------------- 1 | 'FEHLER: ', 4 | 'mailjet-error-client' => 'Mailjet Authentifizierung fehlgeschlagen.', 5 | 'mailjet-error-contact' => 'Kontakt \'{email}\' konnte nicht erstellt werden.', 6 | 'mailjet-error-contactlist-change' => 'Kontaktliste \'{contactlist}\' verweigerte \'{cmd}\' beim Kontakt \'{email}\'.', 7 | 'mailjet-error-contactslist' => 'Kontaktliste \'{contactlist}\' ungültig.', 8 | 'mailjet-error-contactslist-create' => 'Erstellen der Kontaktsliste \'{contactlist}\' fehlgeschlagen.', 9 | 'mailjet-error-invalid-keys' => 'Mailjet Zugang ungültig.', 10 | 'mailjet-error-mustache-file' => 'Mustache Vorlage-Datei fehlt: \'{file}\'.', 11 | 'mailjet-error-newsletter' => 'Newsletter \'{newsletter}\' ungültig.', 12 | 'mailjet-error-newsletter-body-missing-keys' => 'Newsletter Body fehlen Werte: {keys}.', 13 | 'mailjet-error-newsletter-create' => 'Erstellen Newsletter \'{newsletter}\' fehlgeschlagen.', 14 | 'mailjet-error-newsletter-html' => 'Newsletter Content \'{newsletter}\' fehlt der HTML-part.', 15 | 'mailjet-error-newsletter-publish' => 'Versenden Newsletter \'{newsletter}\' an Kontaktsliste \'{contactlist}\' fehlgeschlagen.', 16 | 'mailjet-error-newsletter-publish-non-draft' => 'Newsletter \'{newsletter}\' an Kontaktliste \'{contactlist}\' bereits veröffentlicht.', 17 | 'mailjet-error-newsletter-update-draft' => 'Aktualisierung Newsletter \'{newsletter}\' mit Kontaktliste \'{contactlist}\' fehlgeschlagen.', 18 | 'mailjet-error-segment' => 'Segment \'{segment}\' ungültig.', 19 | 'mailjet-error-sendername' => 'Sendername für \'{email}\' ungültig.', 20 | 'mailjet-error-sendmail-failed' => 'Email an \'{email}\' konnte nicht versandt werden.', 21 | 'mailjet-success-newsletter-publish' => 'Newsletter \'{newsletter}\' wurde an Kontaktsliste \'{contactlist}\' veröffentlicht.', 22 | 'mailjet-success-newsletter-test' => 'Newsletter \'{newsletter}\' TEST wurde an {email} versandt.{service}', 23 | ]); 24 | -------------------------------------------------------------------------------- /languages/en.php: -------------------------------------------------------------------------------- 1 | 'ERROR: ', 4 | 'mailjet-error-client' => 'Mailjet authentification failed.', 5 | 'mailjet-error-contact' => 'Contact \'{email}\' could not be created.', 6 | 'mailjet-error-contactlist-change' => 'Contactlist \'{contactlist}\' rejected \'{cmd}\' of contact \'{email}\'.', 7 | 'mailjet-error-contactslist' => 'Contactlist \'{contactlist}\' not valid.', 8 | 'mailjet-error-contactslist-create' => 'Creating Contactslist \'{contactlist}\' failed.', 9 | 'mailjet-error-invalid-keys' => 'Mailjet keys invalid.', 10 | 'mailjet-error-mustache-file' => 'Mustache template file is missing: \'{file}\'.', 11 | 'mailjet-error-newsletter' => 'Newsletter \'{newsletter}\' not valid.', 12 | 'mailjet-error-newsletter-body-missing-keys' => 'Newsletter Body is missing keys: {keys}.', 13 | 'mailjet-error-newsletter-create' => 'Creating Newsletter \'{newsletter}\' failed.', 14 | 'mailjet-error-newsletter-html' => 'Newsletter Content \'{newsletter}\' is missing HTML-part.', 15 | 'mailjet-error-newsletter-publish' => 'Sending Newsletter \'{newsletter}\' to Contactslist \'{contactlist}\' failed.', 16 | 'mailjet-error-newsletter-publish-non-draft' => 'Newsletter \'{newsletter}\' already published with Contactlist \'{contactlist}\'.', 17 | 'mailjet-error-newsletter-update-draft' => 'Newsletter \'{newsletter}\' with Contactlist \'{contactlist}\' could not be updated.', 18 | 'mailjet-error-segment' => 'Segment \'{segment}\' not valid.', 19 | 'mailjet-error-sendername' => 'Sendername not found for \'{email}\'.', 20 | 'mailjet-error-sendmail-failed' => 'The email to \'{email}\' could not be sent.', 21 | 'mailjet-success-newsletter-publish' => 'Newsletter \'{newsletter}\' published to Contactslist \'{contactlist}\'.', 22 | 'mailjet-success-newsletter-test' => 'Newsletter \'{newsletter}\' TEST sent to {email}.{service}', 23 | ]); 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kirby-mailjet", 3 | "description": "Kirby Mailjet makes sending emails with Mailjet simple.", 4 | "version": "0.9.1", 5 | "author": "Bruno Meilick", 6 | "type": "kirby-plugin", 7 | "license": "Commercial" 8 | } 9 | -------------------------------------------------------------------------------- /snippets/mj-example-block-footer.html: -------------------------------------------------------------------------------- 1 |
{{ footer }}

-------------------------------------------------------------------------------- /snippets/mj-example-block-footer.php: -------------------------------------------------------------------------------- 1 | $data->text()->html()->value(), // string not Field-Object! 13 | 'facebook' => url($data->facebook()), 14 | 'googleplus' => url($data->googleplus()), 15 | ]; 16 | 17 | //a::show($mustachedata); 18 | if (isset($json) && $json) { 19 | echo a::json($mustachedata); 20 | } else { 21 | echo KirbyMailjet::renderMustache($htmlFile, $mustachedata); 22 | } 23 | } 24 | 25 | /************************************ 26 | * Kirbymailjet::buildMJML CALL 27 | */ 28 | if ($isPanelBuilder == false): 29 | 30 | $snippet = basename(__FILE__, '.php'); 31 | ?> 32 | 33 | 34 | 35 | {{ footer }} 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /snippets/mj-example-block-head.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | .link, .link:active, .link:visited { 4 | color: #71feac; 5 | text-decoration: none; 6 | } 7 | .link:hover { 8 | color: #71feac; 9 | text-decoration: underline; 10 | } 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /snippets/mj-example-block-headline.html: -------------------------------------------------------------------------------- 1 |
{{ headline }}
2 | -------------------------------------------------------------------------------- /snippets/mj-example-block-headline.php: -------------------------------------------------------------------------------- 1 | $data->headline()->html()->value(), // string not Field-Object! 13 | ]; 14 | 15 | //a::show($mustachedata); 16 | if (isset($json) && $json) { 17 | echo a::json($mustachedata); 18 | } else { 19 | echo KirbyMailjet::renderMustache($htmlFile, $mustachedata); 20 | } 21 | } 22 | 23 | /************************************ 24 | * Kirbymailjet::buildMJML CALL 25 | */ 26 | if ($isPanelBuilder == false): 27 | 28 | $snippet = basename(__FILE__, '.php'); 29 | ?> 30 | 31 | 32 | 33 | {{ headline }} 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /snippets/mj-example-block-hero.html: -------------------------------------------------------------------------------- 1 |
{{ heroheadline }}
{{ herobutton }}
2 | -------------------------------------------------------------------------------- /snippets/mj-example-block-hero.php: -------------------------------------------------------------------------------- 1 | $data->heroheadline()->html()->value(), // string not Field-Object! 13 | 'herobutton' => $data->herobutton()->html()->value(), // string not Field-Object! 14 | 'herolink' => url($data->herolink()->value()), 15 | 'heroimage' => url($data->heroimage()->value()), 16 | ]; 17 | 18 | //a::show($mustachedata); 19 | if (isset($json) && $json) { 20 | echo a::json($mustachedata); 21 | } else { 22 | echo KirbyMailjet::renderMustache($htmlFile, $mustachedata); 23 | } 24 | } 25 | 26 | /************************************ 27 | * Kirbymailjet::buildMJML CALL 28 | */ 29 | if ($isPanelBuilder == false): 30 | 31 | $snippet = basename(__FILE__, '.php'); 32 | ?> 33 | 34 | 35 | 36 | 37 | {{ heroheadline }} 38 | {{ herobutton }} 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /snippets/mj-example-block-news.html: -------------------------------------------------------------------------------- 1 |
{{ newsheadline }}
2 |
{{# news }}
{{ date }}
{{ text }}
{{/ news }}
3 | -------------------------------------------------------------------------------- /snippets/mj-example-block-news.php: -------------------------------------------------------------------------------- 1 | children()/*->visible()*/ as $subpage) { 13 | $utm = implode([ 14 | '?utm_source='.urlencode(site()->title()->value()), 15 | '&utm_medium=email', 16 | '&utm_campaign='.$page->slug(), // using slug of newsletter, not slug of subpage 17 | ]); 18 | $news[] = [ 19 | 'date' => date('m/d/Y', $subpage->modified()), 20 | 'text' => $subpage->text()->html()->toString(), 21 | 'link' => url($subpage->url().$utm), 22 | ]; 23 | } 24 | 25 | $mustachedata = [ 26 | 'newsheadline' => $data->newsheadline()->html()->value(), 27 | 'news' => $news, 28 | ]; 29 | 30 | //a::show($mustachedata); 31 | if (isset($json) && $json) { 32 | echo a::json($mustachedata); 33 | } else { 34 | echo KirbyMailjet::renderMustache($htmlFile, $mustachedata); 35 | } 36 | } 37 | 38 | /************************************ 39 | * Kirbymailjet::buildMJML CALL 40 | */ 41 | if ($isPanelBuilder == false): 42 | 43 | $snippet = basename(__FILE__, '.php'); 44 | ?> 45 | 46 | 47 | 48 | {{ newsheadline }} 49 | 50 | 51 | 52 | {{# news }} 53 | 54 | 55 | {{ date }} 56 | 57 | 58 | {{ text }} 59 | 60 | 61 | 62 | 63 | 64 | {{/ news }} 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /snippets/mj-example-block-text.html: -------------------------------------------------------------------------------- 1 |
{{ text }}
2 | -------------------------------------------------------------------------------- /snippets/mj-example-block-text.php: -------------------------------------------------------------------------------- 1 | $data->text()->kirbytext()->toString(), // string not Field-Object! 13 | ]; 14 | 15 | //a::show($mustachedata); 16 | if (isset($json) && $json) { 17 | echo a::json($mustachedata); 18 | } else { 19 | echo KirbyMailjet::renderMustache($htmlFile, $mustachedata); 20 | } 21 | } 22 | 23 | /************************************ 24 | * Kirbymailjet::buildMJML CALL 25 | */ 26 | if ($isPanelBuilder == false): 27 | 28 | $snippet = basename(__FILE__, '.php'); 29 | ?> 30 | 31 | 32 | 33 | {{ text }} 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /snippets/mj-example-email.mjml: -------------------------------------------------------------------------------- 1 | 2 | 3 | .link, .link:active, .link:visited { color: #71feac; text-decoration: none; } .link:hover { color: #71feac; text-decoration: underline; } 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | {{ headline }} 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | {{ text }} 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | {{ footer }} 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /snippets/mj-example-email.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /snippets/mj-example-form-error.php: -------------------------------------------------------------------------------- 1 | 2 | error($field)): ?> 3 |

', $form->error($field)) ?>

4 | -------------------------------------------------------------------------------- /snippets/mj-example-newsletter.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /templates/mj-example.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <?= $page->title() ?> 5 | 6 | 25 | 26 | 27 |
28 |

title() ?>

29 |
Edit in Panel Github Docs 30 | mjml Online Editor 31 |

32 |
33 | 34 | user()): ?> 35 |
Kirbymailjet::hash()]) ?>
36 | 37 | 38 |
39 | 40 |
41 | 42 | 43 | 67 | 68 | 69 |
70 |

Status:

71 |
72 | 73 |
74 |

Newsletter Test Contactslist Subscription

75 | 76 |

You have to create firstname and lastname as custom Contact-Properties in your Mailjet-Dashboard.

77 | 78 | 79 | error('firstname')): ?> class="error" name="firstname" type="text" value="old('firstname') ?>"> 80 | 'firstname']) ?> 81 | 82 | 83 | error('lastname')): ?> class="error" name="lastname" type="text" value="old('lastname') ?>"> 84 | 'lastname']) ?> 85 | 86 | 87 | error('email')): ?> class="error" name="email" type="email" value="old('email') ?>"> 88 | 'email']) ?> 89 | 90 | 91 | 92 | 93 | \Uniform\Actions\EmailAction::class]) ?> 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /vendor/autoload.php: -------------------------------------------------------------------------------- 1 | $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php', 10 | 'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php', 11 | 'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php', 12 | '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', 13 | ); 14 | -------------------------------------------------------------------------------- /vendor/composer/autoload_namespaces.php: -------------------------------------------------------------------------------- 1 | array($vendorDir . '/mustache/mustache/src'), 10 | 'Mailjet' => array($vendorDir . '/mailjet/mailjet-apiv3-php/src'), 11 | ); 12 | -------------------------------------------------------------------------------- /vendor/composer/autoload_psr4.php: -------------------------------------------------------------------------------- 1 | array($vendorDir . '/psr/http-message/src'), 10 | 'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'), 11 | 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'), 12 | 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'), 13 | ); 14 | -------------------------------------------------------------------------------- /vendor/composer/autoload_real.php: -------------------------------------------------------------------------------- 1 | = 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\ComposerStaticInit41fed2b187b6f46bc4e1144e5fe7fe3d::getInitializer($loader)); 31 | } else { 32 | $map = require __DIR__ . '/autoload_namespaces.php'; 33 | foreach ($map as $namespace => $path) { 34 | $loader->set($namespace, $path); 35 | } 36 | 37 | $map = require __DIR__ . '/autoload_psr4.php'; 38 | foreach ($map as $namespace => $path) { 39 | $loader->setPsr4($namespace, $path); 40 | } 41 | 42 | $classMap = require __DIR__ . '/autoload_classmap.php'; 43 | if ($classMap) { 44 | $loader->addClassMap($classMap); 45 | } 46 | } 47 | 48 | $loader->register(true); 49 | 50 | if ($useStaticLoader) { 51 | $includeFiles = Composer\Autoload\ComposerStaticInit41fed2b187b6f46bc4e1144e5fe7fe3d::$files; 52 | } else { 53 | $includeFiles = require __DIR__ . '/autoload_files.php'; 54 | } 55 | foreach ($includeFiles as $fileIdentifier => $file) { 56 | composerRequire41fed2b187b6f46bc4e1144e5fe7fe3d($fileIdentifier, $file); 57 | } 58 | 59 | return $loader; 60 | } 61 | } 62 | 63 | function composerRequire41fed2b187b6f46bc4e1144e5fe7fe3d($fileIdentifier, $file) 64 | { 65 | if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { 66 | require $file; 67 | 68 | $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/guzzle/src/ClientInterface.php: -------------------------------------------------------------------------------- 1 | filename = $cookieFile; 27 | $this->storeSessionCookies = $storeSessionCookies; 28 | 29 | if (file_exists($cookieFile)) { 30 | $this->load($cookieFile); 31 | } 32 | } 33 | 34 | /** 35 | * Saves the file when shutting down 36 | */ 37 | public function __destruct() 38 | { 39 | $this->save($this->filename); 40 | } 41 | 42 | /** 43 | * Saves the cookies to a file. 44 | * 45 | * @param string $filename File to save 46 | * @throws \RuntimeException if the file cannot be found or created 47 | */ 48 | public function save($filename) 49 | { 50 | $json = []; 51 | foreach ($this as $cookie) { 52 | /** @var SetCookie $cookie */ 53 | if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) { 54 | $json[] = $cookie->toArray(); 55 | } 56 | } 57 | 58 | $jsonStr = \GuzzleHttp\json_encode($json); 59 | if (false === file_put_contents($filename, $jsonStr)) { 60 | throw new \RuntimeException("Unable to save file {$filename}"); 61 | } 62 | } 63 | 64 | /** 65 | * Load cookies from a JSON formatted file. 66 | * 67 | * Old cookies are kept unless overwritten by newly loaded ones. 68 | * 69 | * @param string $filename Cookie file to load. 70 | * @throws \RuntimeException if the file cannot be loaded. 71 | */ 72 | public function load($filename) 73 | { 74 | $json = file_get_contents($filename); 75 | if (false === $json) { 76 | throw new \RuntimeException("Unable to load file {$filename}"); 77 | } elseif ($json === '') { 78 | return; 79 | } 80 | 81 | $data = \GuzzleHttp\json_decode($json, true); 82 | if (is_array($data)) { 83 | foreach (json_decode($json, true) as $cookie) { 84 | $this->setCookie(new SetCookie($cookie)); 85 | } 86 | } elseif (strlen($data)) { 87 | throw new \RuntimeException("Invalid cookie file: {$filename}"); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php: -------------------------------------------------------------------------------- 1 | sessionKey = $sessionKey; 26 | $this->storeSessionCookies = $storeSessionCookies; 27 | $this->load(); 28 | } 29 | 30 | /** 31 | * Saves cookies to session when shutting down 32 | */ 33 | public function __destruct() 34 | { 35 | $this->save(); 36 | } 37 | 38 | /** 39 | * Save cookies to the client session 40 | */ 41 | public function save() 42 | { 43 | $json = []; 44 | foreach ($this as $cookie) { 45 | /** @var SetCookie $cookie */ 46 | if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) { 47 | $json[] = $cookie->toArray(); 48 | } 49 | } 50 | 51 | $_SESSION[$this->sessionKey] = json_encode($json); 52 | } 53 | 54 | /** 55 | * Load the contents of the client session into the data array 56 | */ 57 | protected function load() 58 | { 59 | if (!isset($_SESSION[$this->sessionKey])) { 60 | return; 61 | } 62 | $data = json_decode($_SESSION[$this->sessionKey], true); 63 | if (is_array($data)) { 64 | foreach ($data as $cookie) { 65 | $this->setCookie(new SetCookie($cookie)); 66 | } 67 | } elseif (strlen($data)) { 68 | throw new \RuntimeException("Invalid cookie data"); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php: -------------------------------------------------------------------------------- 1 | stream = $stream; 16 | $msg = $msg ?: 'Could not seek the stream to position ' . $pos; 17 | parent::__construct($msg); 18 | } 19 | 20 | /** 21 | * @return StreamInterface 22 | */ 23 | public function getStream() 24 | { 25 | return $this->stream; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/guzzle/src/Exception/ServerException.php: -------------------------------------------------------------------------------- 1 | factory = isset($options['handle_factory']) 29 | ? $options['handle_factory'] 30 | : new CurlFactory(3); 31 | } 32 | 33 | public function __invoke(RequestInterface $request, array $options) 34 | { 35 | if (isset($options['delay'])) { 36 | usleep($options['delay'] * 1000); 37 | } 38 | 39 | $easy = $this->factory->create($request, $options); 40 | curl_exec($easy->handle); 41 | $easy->errno = curl_errno($easy->handle); 42 | 43 | return CurlFactory::finish($this, $easy, $this->factory); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php: -------------------------------------------------------------------------------- 1 | headers)) { 48 | throw new \RuntimeException('No headers have been received'); 49 | } 50 | 51 | // HTTP-version SP status-code SP reason-phrase 52 | $startLine = explode(' ', array_shift($this->headers), 3); 53 | $headers = \GuzzleHttp\headers_from_lines($this->headers); 54 | $normalizedKeys = \GuzzleHttp\normalize_header_keys($headers); 55 | 56 | if (!empty($this->options['decode_content']) 57 | && isset($normalizedKeys['content-encoding']) 58 | ) { 59 | $headers['x-encoded-content-encoding'] 60 | = $headers[$normalizedKeys['content-encoding']]; 61 | unset($headers[$normalizedKeys['content-encoding']]); 62 | if (isset($normalizedKeys['content-length'])) { 63 | $headers['x-encoded-content-length'] 64 | = $headers[$normalizedKeys['content-length']]; 65 | 66 | $bodyLength = (int) $this->sink->getSize(); 67 | if ($bodyLength) { 68 | $headers[$normalizedKeys['content-length']] = $bodyLength; 69 | } else { 70 | unset($headers[$normalizedKeys['content-length']]); 71 | } 72 | } 73 | } 74 | 75 | // Attach a response to the easy handle with the parsed headers. 76 | $this->response = new Response( 77 | $startLine[1], 78 | $headers, 79 | $this->sink, 80 | substr($startLine[0], 5), 81 | isset($startLine[2]) ? (string) $startLine[2] : null 82 | ); 83 | } 84 | 85 | public function __get($name) 86 | { 87 | $msg = $name === 'handle' 88 | ? 'The EasyHandle has been released' 89 | : 'Invalid property: ' . $name; 90 | throw new \BadMethodCallException($msg); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/guzzle/src/Handler/Proxy.php: -------------------------------------------------------------------------------- 1 | nextHandler = $nextHandler; 23 | } 24 | 25 | /** 26 | * @param RequestInterface $request 27 | * @param array $options 28 | * 29 | * @return PromiseInterface 30 | */ 31 | public function __invoke(RequestInterface $request, array $options) 32 | { 33 | $fn = $this->nextHandler; 34 | 35 | // Don't do anything if the request has no body. 36 | if ($request->getBody()->getSize() === 0) { 37 | return $fn($request, $options); 38 | } 39 | 40 | $modify = []; 41 | 42 | // Add a default content-type if possible. 43 | if (!$request->hasHeader('Content-Type')) { 44 | if ($uri = $request->getBody()->getMetadata('uri')) { 45 | if ($type = Psr7\mimetype_from_filename($uri)) { 46 | $modify['set_headers']['Content-Type'] = $type; 47 | } 48 | } 49 | } 50 | 51 | // Add a default content-length or transfer-encoding header. 52 | if (!$request->hasHeader('Content-Length') 53 | && !$request->hasHeader('Transfer-Encoding') 54 | ) { 55 | $size = $request->getBody()->getSize(); 56 | if ($size !== null) { 57 | $modify['set_headers']['Content-Length'] = $size; 58 | } else { 59 | $modify['set_headers']['Transfer-Encoding'] = 'chunked'; 60 | } 61 | } 62 | 63 | // Add the expect header if needed. 64 | $this->addExpectHeader($request, $options, $modify); 65 | 66 | return $fn(Psr7\modify_request($request, $modify), $options); 67 | } 68 | 69 | private function addExpectHeader( 70 | RequestInterface $request, 71 | array $options, 72 | array &$modify 73 | ) { 74 | // Determine if the Expect header should be used 75 | if ($request->hasHeader('Expect')) { 76 | return; 77 | } 78 | 79 | $expect = isset($options['expect']) ? $options['expect'] : null; 80 | 81 | // Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0 82 | if ($expect === false || $request->getProtocolVersion() < 1.1) { 83 | return; 84 | } 85 | 86 | // The expect header is unconditionally enabled 87 | if ($expect === true) { 88 | $modify['set_headers']['Expect'] = '100-Continue'; 89 | return; 90 | } 91 | 92 | // By default, send the expect header when the payload is > 1mb 93 | if ($expect === null) { 94 | $expect = 1048576; 95 | } 96 | 97 | // Always add if the body cannot be rewound, the size cannot be 98 | // determined, or the size is greater than the cutoff threshold 99 | $body = $request->getBody(); 100 | $size = $body->getSize(); 101 | 102 | if ($size === null || $size >= (int) $expect || !$body->isSeekable()) { 103 | $modify['set_headers']['Expect'] = '100-Continue'; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/guzzle/src/RetryMiddleware.php: -------------------------------------------------------------------------------- 1 | decider = $decider; 38 | $this->nextHandler = $nextHandler; 39 | $this->delay = $delay ?: __CLASS__ . '::exponentialDelay'; 40 | } 41 | 42 | /** 43 | * Default exponential backoff delay function. 44 | * 45 | * @param $retries 46 | * 47 | * @return int 48 | */ 49 | public static function exponentialDelay($retries) 50 | { 51 | return (int) pow(2, $retries - 1); 52 | } 53 | 54 | /** 55 | * @param RequestInterface $request 56 | * @param array $options 57 | * 58 | * @return PromiseInterface 59 | */ 60 | public function __invoke(RequestInterface $request, array $options) 61 | { 62 | if (!isset($options['retries'])) { 63 | $options['retries'] = 0; 64 | } 65 | 66 | $fn = $this->nextHandler; 67 | return $fn($request, $options) 68 | ->then( 69 | $this->onFulfilled($request, $options), 70 | $this->onRejected($request, $options) 71 | ); 72 | } 73 | 74 | private function onFulfilled(RequestInterface $req, array $options) 75 | { 76 | return function ($value) use ($req, $options) { 77 | if (!call_user_func( 78 | $this->decider, 79 | $options['retries'], 80 | $req, 81 | $value, 82 | null 83 | )) { 84 | return $value; 85 | } 86 | return $this->doRetry($req, $options, $value); 87 | }; 88 | } 89 | 90 | private function onRejected(RequestInterface $req, array $options) 91 | { 92 | return function ($reason) use ($req, $options) { 93 | if (!call_user_func( 94 | $this->decider, 95 | $options['retries'], 96 | $req, 97 | null, 98 | $reason 99 | )) { 100 | return \GuzzleHttp\Promise\rejection_for($reason); 101 | } 102 | return $this->doRetry($req, $options); 103 | }; 104 | } 105 | 106 | private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null) 107 | { 108 | $options['delay'] = call_user_func($this->delay, ++$options['retries'], $response); 109 | 110 | return $this($request, $options); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/guzzle/src/TransferStats.php: -------------------------------------------------------------------------------- 1 | request = $request; 35 | $this->response = $response; 36 | $this->transferTime = $transferTime; 37 | $this->handlerErrorData = $handlerErrorData; 38 | $this->handlerStats = $handlerStats; 39 | } 40 | 41 | /** 42 | * @return RequestInterface 43 | */ 44 | public function getRequest() 45 | { 46 | return $this->request; 47 | } 48 | 49 | /** 50 | * Returns the response that was received (if any). 51 | * 52 | * @return ResponseInterface|null 53 | */ 54 | public function getResponse() 55 | { 56 | return $this->response; 57 | } 58 | 59 | /** 60 | * Returns true if a response was received. 61 | * 62 | * @return bool 63 | */ 64 | public function hasResponse() 65 | { 66 | return $this->response !== null; 67 | } 68 | 69 | /** 70 | * Gets handler specific error data. 71 | * 72 | * This might be an exception, a integer representing an error code, or 73 | * anything else. Relying on this value assumes that you know what handler 74 | * you are using. 75 | * 76 | * @return mixed 77 | */ 78 | public function getHandlerErrorData() 79 | { 80 | return $this->handlerErrorData; 81 | } 82 | 83 | /** 84 | * Get the effective URI the request was sent to. 85 | * 86 | * @return UriInterface 87 | */ 88 | public function getEffectiveUri() 89 | { 90 | return $this->request->getUri(); 91 | } 92 | 93 | /** 94 | * Get the estimated time the request was being transferred by the handler. 95 | * 96 | * @return float Time in seconds. 97 | */ 98 | public function getTransferTime() 99 | { 100 | return $this->transferTime; 101 | } 102 | 103 | /** 104 | * Gets an array of all of the handler specific transfer data. 105 | * 106 | * @return array 107 | */ 108 | public function getHandlerStats() 109 | { 110 | return $this->handlerStats; 111 | } 112 | 113 | /** 114 | * Get a specific handler statistic from the handler by name. 115 | * 116 | * @param string $stat Handler specific transfer stat to retrieve. 117 | * 118 | * @return mixed|null 119 | */ 120 | public function getHandlerStat($stat) 121 | { 122 | return isset($this->handlerStats[$stat]) 123 | ? $this->handlerStats[$stat] 124 | : null; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/guzzle/src/functions_include.php: -------------------------------------------------------------------------------- 1 | then(function ($v) { echo $v; }); 37 | * 38 | * @param callable $generatorFn Generator function to wrap into a promise. 39 | * 40 | * @return Promise 41 | * @link https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration 42 | */ 43 | final class Coroutine implements PromiseInterface 44 | { 45 | /** 46 | * @var PromiseInterface|null 47 | */ 48 | private $currentPromise; 49 | 50 | /** 51 | * @var Generator 52 | */ 53 | private $generator; 54 | 55 | /** 56 | * @var Promise 57 | */ 58 | private $result; 59 | 60 | public function __construct(callable $generatorFn) 61 | { 62 | $this->generator = $generatorFn(); 63 | $this->result = new Promise(function () { 64 | while (isset($this->currentPromise)) { 65 | $this->currentPromise->wait(); 66 | } 67 | }); 68 | $this->nextCoroutine($this->generator->current()); 69 | } 70 | 71 | public function then( 72 | callable $onFulfilled = null, 73 | callable $onRejected = null 74 | ) { 75 | return $this->result->then($onFulfilled, $onRejected); 76 | } 77 | 78 | public function otherwise(callable $onRejected) 79 | { 80 | return $this->result->otherwise($onRejected); 81 | } 82 | 83 | public function wait($unwrap = true) 84 | { 85 | return $this->result->wait($unwrap); 86 | } 87 | 88 | public function getState() 89 | { 90 | return $this->result->getState(); 91 | } 92 | 93 | public function resolve($value) 94 | { 95 | $this->result->resolve($value); 96 | } 97 | 98 | public function reject($reason) 99 | { 100 | $this->result->reject($reason); 101 | } 102 | 103 | public function cancel() 104 | { 105 | $this->currentPromise->cancel(); 106 | $this->result->cancel(); 107 | } 108 | 109 | private function nextCoroutine($yielded) 110 | { 111 | $this->currentPromise = promise_for($yielded) 112 | ->then([$this, '_handleSuccess'], [$this, '_handleFailure']); 113 | } 114 | 115 | /** 116 | * @internal 117 | */ 118 | public function _handleSuccess($value) 119 | { 120 | unset($this->currentPromise); 121 | try { 122 | $next = $this->generator->send($value); 123 | if ($this->generator->valid()) { 124 | $this->nextCoroutine($next); 125 | } else { 126 | $this->result->resolve($value); 127 | } 128 | } catch (Exception $exception) { 129 | $this->result->reject($exception); 130 | } catch (Throwable $throwable) { 131 | $this->result->reject($throwable); 132 | } 133 | } 134 | 135 | /** 136 | * @internal 137 | */ 138 | public function _handleFailure($reason) 139 | { 140 | unset($this->currentPromise); 141 | try { 142 | $nextYield = $this->generator->throw(exception_for($reason)); 143 | // The throw was caught, so keep iterating on the coroutine 144 | $this->nextCoroutine($nextYield); 145 | } catch (Exception $exception) { 146 | $this->result->reject($exception); 147 | } catch (Throwable $throwable) { 148 | $this->result->reject($throwable); 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/promises/src/FulfilledPromise.php: -------------------------------------------------------------------------------- 1 | value = $value; 22 | } 23 | 24 | public function then( 25 | callable $onFulfilled = null, 26 | callable $onRejected = null 27 | ) { 28 | // Return itself if there is no onFulfilled function. 29 | if (!$onFulfilled) { 30 | return $this; 31 | } 32 | 33 | $queue = queue(); 34 | $p = new Promise([$queue, 'run']); 35 | $value = $this->value; 36 | $queue->add(static function () use ($p, $value, $onFulfilled) { 37 | if ($p->getState() === self::PENDING) { 38 | try { 39 | $p->resolve($onFulfilled($value)); 40 | } catch (\Throwable $e) { 41 | $p->reject($e); 42 | } catch (\Exception $e) { 43 | $p->reject($e); 44 | } 45 | } 46 | }); 47 | 48 | return $p; 49 | } 50 | 51 | public function otherwise(callable $onRejected) 52 | { 53 | return $this->then(null, $onRejected); 54 | } 55 | 56 | public function wait($unwrap = true, $defaultDelivery = null) 57 | { 58 | return $unwrap ? $this->value : null; 59 | } 60 | 61 | public function getState() 62 | { 63 | return self::FULFILLED; 64 | } 65 | 66 | public function resolve($value) 67 | { 68 | if ($value !== $this->value) { 69 | throw new \LogicException("Cannot resolve a fulfilled promise"); 70 | } 71 | } 72 | 73 | public function reject($reason) 74 | { 75 | throw new \LogicException("Cannot reject a fulfilled promise"); 76 | } 77 | 78 | public function cancel() 79 | { 80 | // pass 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/promises/src/PromiseInterface.php: -------------------------------------------------------------------------------- 1 | reason = $reason; 22 | } 23 | 24 | public function then( 25 | callable $onFulfilled = null, 26 | callable $onRejected = null 27 | ) { 28 | // If there's no onRejected callback then just return self. 29 | if (!$onRejected) { 30 | return $this; 31 | } 32 | 33 | $queue = queue(); 34 | $reason = $this->reason; 35 | $p = new Promise([$queue, 'run']); 36 | $queue->add(static function () use ($p, $reason, $onRejected) { 37 | if ($p->getState() === self::PENDING) { 38 | try { 39 | // Return a resolved promise if onRejected does not throw. 40 | $p->resolve($onRejected($reason)); 41 | } catch (\Throwable $e) { 42 | // onRejected threw, so return a rejected promise. 43 | $p->reject($e); 44 | } catch (\Exception $e) { 45 | // onRejected threw, so return a rejected promise. 46 | $p->reject($e); 47 | } 48 | } 49 | }); 50 | 51 | return $p; 52 | } 53 | 54 | public function otherwise(callable $onRejected) 55 | { 56 | return $this->then(null, $onRejected); 57 | } 58 | 59 | public function wait($unwrap = true, $defaultDelivery = null) 60 | { 61 | if ($unwrap) { 62 | throw exception_for($this->reason); 63 | } 64 | } 65 | 66 | public function getState() 67 | { 68 | return self::REJECTED; 69 | } 70 | 71 | public function resolve($value) 72 | { 73 | throw new \LogicException("Cannot resolve a rejected promise"); 74 | } 75 | 76 | public function reject($reason) 77 | { 78 | if ($reason !== $this->reason) { 79 | throw new \LogicException("Cannot reject a rejected promise"); 80 | } 81 | } 82 | 83 | public function cancel() 84 | { 85 | // pass 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/promises/src/RejectionException.php: -------------------------------------------------------------------------------- 1 | reason = $reason; 21 | 22 | $message = 'The promise was rejected'; 23 | 24 | if ($description) { 25 | $message .= ' with reason: ' . $description; 26 | } elseif (is_string($reason) 27 | || (is_object($reason) && method_exists($reason, '__toString')) 28 | ) { 29 | $message .= ' with reason: ' . $this->reason; 30 | } elseif ($reason instanceof \JsonSerializable) { 31 | $message .= ' with reason: ' 32 | . json_encode($this->reason, JSON_PRETTY_PRINT); 33 | } 34 | 35 | parent::__construct($message); 36 | } 37 | 38 | /** 39 | * Returns the rejection reason. 40 | * 41 | * @return mixed 42 | */ 43 | public function getReason() 44 | { 45 | return $this->reason; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/promises/src/TaskQueue.php: -------------------------------------------------------------------------------- 1 | run(); 12 | */ 13 | class TaskQueue implements TaskQueueInterface 14 | { 15 | private $enableShutdown = true; 16 | private $queue = []; 17 | 18 | public function __construct($withShutdown = true) 19 | { 20 | if ($withShutdown) { 21 | register_shutdown_function(function () { 22 | if ($this->enableShutdown) { 23 | // Only run the tasks if an E_ERROR didn't occur. 24 | $err = error_get_last(); 25 | if (!$err || ($err['type'] ^ E_ERROR)) { 26 | $this->run(); 27 | } 28 | } 29 | }); 30 | } 31 | } 32 | 33 | public function isEmpty() 34 | { 35 | return !$this->queue; 36 | } 37 | 38 | public function add(callable $task) 39 | { 40 | $this->queue[] = $task; 41 | } 42 | 43 | public function run() 44 | { 45 | /** @var callable $task */ 46 | while ($task = array_shift($this->queue)) { 47 | $task(); 48 | } 49 | } 50 | 51 | /** 52 | * The task queue will be run and exhausted by default when the process 53 | * exits IFF the exit is not the result of a PHP E_ERROR error. 54 | * 55 | * You can disable running the automatic shutdown of the queue by calling 56 | * this function. If you disable the task queue shutdown process, then you 57 | * MUST either run the task queue (as a result of running your event loop 58 | * or manually using the run() method) or wait on each outstanding promise. 59 | * 60 | * Note: This shutdown will occur before any destructors are triggered. 61 | */ 62 | public function disableShutdown() 63 | { 64 | $this->enableShutdown = false; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/promises/src/TaskQueueInterface.php: -------------------------------------------------------------------------------- 1 | hwm = $hwm; 29 | } 30 | 31 | public function __toString() 32 | { 33 | return $this->getContents(); 34 | } 35 | 36 | public function getContents() 37 | { 38 | $buffer = $this->buffer; 39 | $this->buffer = ''; 40 | 41 | return $buffer; 42 | } 43 | 44 | public function close() 45 | { 46 | $this->buffer = ''; 47 | } 48 | 49 | public function detach() 50 | { 51 | $this->close(); 52 | } 53 | 54 | public function getSize() 55 | { 56 | return strlen($this->buffer); 57 | } 58 | 59 | public function isReadable() 60 | { 61 | return true; 62 | } 63 | 64 | public function isWritable() 65 | { 66 | return true; 67 | } 68 | 69 | public function isSeekable() 70 | { 71 | return false; 72 | } 73 | 74 | public function rewind() 75 | { 76 | $this->seek(0); 77 | } 78 | 79 | public function seek($offset, $whence = SEEK_SET) 80 | { 81 | throw new \RuntimeException('Cannot seek a BufferStream'); 82 | } 83 | 84 | public function eof() 85 | { 86 | return strlen($this->buffer) === 0; 87 | } 88 | 89 | public function tell() 90 | { 91 | throw new \RuntimeException('Cannot determine the position of a BufferStream'); 92 | } 93 | 94 | /** 95 | * Reads data from the buffer. 96 | */ 97 | public function read($length) 98 | { 99 | $currentLength = strlen($this->buffer); 100 | 101 | if ($length >= $currentLength) { 102 | // No need to slice the buffer because we don't have enough data. 103 | $result = $this->buffer; 104 | $this->buffer = ''; 105 | } else { 106 | // Slice up the result to provide a subset of the buffer. 107 | $result = substr($this->buffer, 0, $length); 108 | $this->buffer = substr($this->buffer, $length); 109 | } 110 | 111 | return $result; 112 | } 113 | 114 | /** 115 | * Writes data to the buffer. 116 | */ 117 | public function write($string) 118 | { 119 | $this->buffer .= $string; 120 | 121 | // TODO: What should happen here? 122 | if (strlen($this->buffer) >= $this->hwm) { 123 | return false; 124 | } 125 | 126 | return strlen($string); 127 | } 128 | 129 | public function getMetadata($key = null) 130 | { 131 | if ($key == 'hwm') { 132 | return $this->hwm; 133 | } 134 | 135 | return $key ? null : []; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/psr7/src/DroppingStream.php: -------------------------------------------------------------------------------- 1 | stream = $stream; 23 | $this->maxLength = $maxLength; 24 | } 25 | 26 | public function write($string) 27 | { 28 | $diff = $this->maxLength - $this->stream->getSize(); 29 | 30 | // Begin returning 0 when the underlying stream is too large. 31 | if ($diff <= 0) { 32 | return 0; 33 | } 34 | 35 | // Write the stream or a subset of the stream if needed. 36 | if (strlen($string) < $diff) { 37 | return $this->stream->write($string); 38 | } 39 | 40 | return $this->stream->write(substr($string, 0, $diff)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/psr7/src/FnStream.php: -------------------------------------------------------------------------------- 1 | methods = $methods; 28 | 29 | // Create the functions on the class 30 | foreach ($methods as $name => $fn) { 31 | $this->{'_fn_' . $name} = $fn; 32 | } 33 | } 34 | 35 | /** 36 | * Lazily determine which methods are not implemented. 37 | * @throws \BadMethodCallException 38 | */ 39 | public function __get($name) 40 | { 41 | throw new \BadMethodCallException(str_replace('_fn_', '', $name) 42 | . '() is not implemented in the FnStream'); 43 | } 44 | 45 | /** 46 | * The close method is called on the underlying stream only if possible. 47 | */ 48 | public function __destruct() 49 | { 50 | if (isset($this->_fn_close)) { 51 | call_user_func($this->_fn_close); 52 | } 53 | } 54 | 55 | /** 56 | * An unserialize would allow the __destruct to run when the unserialized value goes out of scope. 57 | * @throws \LogicException 58 | */ 59 | public function __wakeup() 60 | { 61 | throw new \LogicException('FnStream should never be unserialized'); 62 | } 63 | 64 | /** 65 | * Adds custom functionality to an underlying stream by intercepting 66 | * specific method calls. 67 | * 68 | * @param StreamInterface $stream Stream to decorate 69 | * @param array $methods Hash of method name to a closure 70 | * 71 | * @return FnStream 72 | */ 73 | public static function decorate(StreamInterface $stream, array $methods) 74 | { 75 | // If any of the required methods were not provided, then simply 76 | // proxy to the decorated stream. 77 | foreach (array_diff(self::$slots, array_keys($methods)) as $diff) { 78 | $methods[$diff] = [$stream, $diff]; 79 | } 80 | 81 | return new self($methods); 82 | } 83 | 84 | public function __toString() 85 | { 86 | return call_user_func($this->_fn___toString); 87 | } 88 | 89 | public function close() 90 | { 91 | return call_user_func($this->_fn_close); 92 | } 93 | 94 | public function detach() 95 | { 96 | return call_user_func($this->_fn_detach); 97 | } 98 | 99 | public function getSize() 100 | { 101 | return call_user_func($this->_fn_getSize); 102 | } 103 | 104 | public function tell() 105 | { 106 | return call_user_func($this->_fn_tell); 107 | } 108 | 109 | public function eof() 110 | { 111 | return call_user_func($this->_fn_eof); 112 | } 113 | 114 | public function isSeekable() 115 | { 116 | return call_user_func($this->_fn_isSeekable); 117 | } 118 | 119 | public function rewind() 120 | { 121 | call_user_func($this->_fn_rewind); 122 | } 123 | 124 | public function seek($offset, $whence = SEEK_SET) 125 | { 126 | call_user_func($this->_fn_seek, $offset, $whence); 127 | } 128 | 129 | public function isWritable() 130 | { 131 | return call_user_func($this->_fn_isWritable); 132 | } 133 | 134 | public function write($string) 135 | { 136 | return call_user_func($this->_fn_write, $string); 137 | } 138 | 139 | public function isReadable() 140 | { 141 | return call_user_func($this->_fn_isReadable); 142 | } 143 | 144 | public function read($length) 145 | { 146 | return call_user_func($this->_fn_read, $length); 147 | } 148 | 149 | public function getContents() 150 | { 151 | return call_user_func($this->_fn_getContents); 152 | } 153 | 154 | public function getMetadata($key = null) 155 | { 156 | return call_user_func($this->_fn_getMetadata, $key); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/psr7/src/InflateStream.php: -------------------------------------------------------------------------------- 1 | read(10); 25 | $filenameHeaderLength = $this->getLengthOfPossibleFilenameHeader($stream, $header); 26 | // Skip the header, that is 10 + length of filename + 1 (nil) bytes 27 | $stream = new LimitStream($stream, -1, 10 + $filenameHeaderLength); 28 | $resource = StreamWrapper::getResource($stream); 29 | stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ); 30 | $this->stream = $stream->isSeekable() ? new Stream($resource) : new NoSeekStream(new Stream($resource)); 31 | } 32 | 33 | /** 34 | * @param StreamInterface $stream 35 | * @param $header 36 | * @return int 37 | */ 38 | private function getLengthOfPossibleFilenameHeader(StreamInterface $stream, $header) 39 | { 40 | $filename_header_length = 0; 41 | 42 | if (substr(bin2hex($header), 6, 2) === '08') { 43 | // we have a filename, read until nil 44 | $filename_header_length = 1; 45 | while ($stream->read(1) !== chr(0)) { 46 | $filename_header_length++; 47 | } 48 | } 49 | 50 | return $filename_header_length; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/psr7/src/LazyOpenStream.php: -------------------------------------------------------------------------------- 1 | filename = $filename; 27 | $this->mode = $mode; 28 | } 29 | 30 | /** 31 | * Creates the underlying stream lazily when required. 32 | * 33 | * @return StreamInterface 34 | */ 35 | protected function createStream() 36 | { 37 | return stream_for(try_fopen($this->filename, $this->mode)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/psr7/src/NoSeekStream.php: -------------------------------------------------------------------------------- 1 | source = $source; 46 | $this->size = isset($options['size']) ? $options['size'] : null; 47 | $this->metadata = isset($options['metadata']) ? $options['metadata'] : []; 48 | $this->buffer = new BufferStream(); 49 | } 50 | 51 | public function __toString() 52 | { 53 | try { 54 | return copy_to_string($this); 55 | } catch (\Exception $e) { 56 | return ''; 57 | } 58 | } 59 | 60 | public function close() 61 | { 62 | $this->detach(); 63 | } 64 | 65 | public function detach() 66 | { 67 | $this->tellPos = false; 68 | $this->source = null; 69 | } 70 | 71 | public function getSize() 72 | { 73 | return $this->size; 74 | } 75 | 76 | public function tell() 77 | { 78 | return $this->tellPos; 79 | } 80 | 81 | public function eof() 82 | { 83 | return !$this->source; 84 | } 85 | 86 | public function isSeekable() 87 | { 88 | return false; 89 | } 90 | 91 | public function rewind() 92 | { 93 | $this->seek(0); 94 | } 95 | 96 | public function seek($offset, $whence = SEEK_SET) 97 | { 98 | throw new \RuntimeException('Cannot seek a PumpStream'); 99 | } 100 | 101 | public function isWritable() 102 | { 103 | return false; 104 | } 105 | 106 | public function write($string) 107 | { 108 | throw new \RuntimeException('Cannot write to a PumpStream'); 109 | } 110 | 111 | public function isReadable() 112 | { 113 | return true; 114 | } 115 | 116 | public function read($length) 117 | { 118 | $data = $this->buffer->read($length); 119 | $readLen = strlen($data); 120 | $this->tellPos += $readLen; 121 | $remaining = $length - $readLen; 122 | 123 | if ($remaining) { 124 | $this->pump($remaining); 125 | $data .= $this->buffer->read($remaining); 126 | $this->tellPos += strlen($data) - $readLen; 127 | } 128 | 129 | return $data; 130 | } 131 | 132 | public function getContents() 133 | { 134 | $result = ''; 135 | while (!$this->eof()) { 136 | $result .= $this->read(1000000); 137 | } 138 | 139 | return $result; 140 | } 141 | 142 | public function getMetadata($key = null) 143 | { 144 | if (!$key) { 145 | return $this->metadata; 146 | } 147 | 148 | return isset($this->metadata[$key]) ? $this->metadata[$key] : null; 149 | } 150 | 151 | private function pump($length) 152 | { 153 | if ($this->source) { 154 | do { 155 | $data = call_user_func($this->source, $length); 156 | if ($data === false || $data === null) { 157 | $this->source = null; 158 | return; 159 | } 160 | $this->buffer->write($data); 161 | $length -= strlen($data); 162 | } while ($length > 0); 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/psr7/src/Request.php: -------------------------------------------------------------------------------- 1 | method = strtoupper($method); 44 | $this->uri = $uri; 45 | $this->setHeaders($headers); 46 | $this->protocol = $version; 47 | 48 | if (!isset($this->headerNames['host'])) { 49 | $this->updateHostFromUri(); 50 | } 51 | 52 | if ($body !== '' && $body !== null) { 53 | $this->stream = stream_for($body); 54 | } 55 | } 56 | 57 | public function getRequestTarget() 58 | { 59 | if ($this->requestTarget !== null) { 60 | return $this->requestTarget; 61 | } 62 | 63 | $target = $this->uri->getPath(); 64 | if ($target == '') { 65 | $target = '/'; 66 | } 67 | if ($this->uri->getQuery() != '') { 68 | $target .= '?' . $this->uri->getQuery(); 69 | } 70 | 71 | return $target; 72 | } 73 | 74 | public function withRequestTarget($requestTarget) 75 | { 76 | if (preg_match('#\s#', $requestTarget)) { 77 | throw new InvalidArgumentException( 78 | 'Invalid request target provided; cannot contain whitespace' 79 | ); 80 | } 81 | 82 | $new = clone $this; 83 | $new->requestTarget = $requestTarget; 84 | return $new; 85 | } 86 | 87 | public function getMethod() 88 | { 89 | return $this->method; 90 | } 91 | 92 | public function withMethod($method) 93 | { 94 | $new = clone $this; 95 | $new->method = strtoupper($method); 96 | return $new; 97 | } 98 | 99 | public function getUri() 100 | { 101 | return $this->uri; 102 | } 103 | 104 | public function withUri(UriInterface $uri, $preserveHost = false) 105 | { 106 | if ($uri === $this->uri) { 107 | return $this; 108 | } 109 | 110 | $new = clone $this; 111 | $new->uri = $uri; 112 | 113 | if (!$preserveHost || !isset($this->headerNames['host'])) { 114 | $new->updateHostFromUri(); 115 | } 116 | 117 | return $new; 118 | } 119 | 120 | private function updateHostFromUri() 121 | { 122 | $host = $this->uri->getHost(); 123 | 124 | if ($host == '') { 125 | return; 126 | } 127 | 128 | if (($port = $this->uri->getPort()) !== null) { 129 | $host .= ':' . $port; 130 | } 131 | 132 | if (isset($this->headerNames['host'])) { 133 | $header = $this->headerNames['host']; 134 | } else { 135 | $header = 'Host'; 136 | $this->headerNames['host'] = 'Host'; 137 | } 138 | // Ensure Host is the first header. 139 | // See: http://tools.ietf.org/html/rfc7230#section-5.4 140 | $this->headers = [$header => [$host]] + $this->headers; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/psr7/src/Response.php: -------------------------------------------------------------------------------- 1 | 'Continue', 17 | 101 => 'Switching Protocols', 18 | 102 => 'Processing', 19 | 200 => 'OK', 20 | 201 => 'Created', 21 | 202 => 'Accepted', 22 | 203 => 'Non-Authoritative Information', 23 | 204 => 'No Content', 24 | 205 => 'Reset Content', 25 | 206 => 'Partial Content', 26 | 207 => 'Multi-status', 27 | 208 => 'Already Reported', 28 | 300 => 'Multiple Choices', 29 | 301 => 'Moved Permanently', 30 | 302 => 'Found', 31 | 303 => 'See Other', 32 | 304 => 'Not Modified', 33 | 305 => 'Use Proxy', 34 | 306 => 'Switch Proxy', 35 | 307 => 'Temporary Redirect', 36 | 400 => 'Bad Request', 37 | 401 => 'Unauthorized', 38 | 402 => 'Payment Required', 39 | 403 => 'Forbidden', 40 | 404 => 'Not Found', 41 | 405 => 'Method Not Allowed', 42 | 406 => 'Not Acceptable', 43 | 407 => 'Proxy Authentication Required', 44 | 408 => 'Request Time-out', 45 | 409 => 'Conflict', 46 | 410 => 'Gone', 47 | 411 => 'Length Required', 48 | 412 => 'Precondition Failed', 49 | 413 => 'Request Entity Too Large', 50 | 414 => 'Request-URI Too Large', 51 | 415 => 'Unsupported Media Type', 52 | 416 => 'Requested range not satisfiable', 53 | 417 => 'Expectation Failed', 54 | 418 => 'I\'m a teapot', 55 | 422 => 'Unprocessable Entity', 56 | 423 => 'Locked', 57 | 424 => 'Failed Dependency', 58 | 425 => 'Unordered Collection', 59 | 426 => 'Upgrade Required', 60 | 428 => 'Precondition Required', 61 | 429 => 'Too Many Requests', 62 | 431 => 'Request Header Fields Too Large', 63 | 451 => 'Unavailable For Legal Reasons', 64 | 500 => 'Internal Server Error', 65 | 501 => 'Not Implemented', 66 | 502 => 'Bad Gateway', 67 | 503 => 'Service Unavailable', 68 | 504 => 'Gateway Time-out', 69 | 505 => 'HTTP Version not supported', 70 | 506 => 'Variant Also Negotiates', 71 | 507 => 'Insufficient Storage', 72 | 508 => 'Loop Detected', 73 | 511 => 'Network Authentication Required', 74 | ]; 75 | 76 | /** @var string */ 77 | private $reasonPhrase = ''; 78 | 79 | /** @var int */ 80 | private $statusCode = 200; 81 | 82 | /** 83 | * @param int $status Status code 84 | * @param array $headers Response headers 85 | * @param string|null|resource|StreamInterface $body Response body 86 | * @param string $version Protocol version 87 | * @param string|null $reason Reason phrase (when empty a default will be used based on the status code) 88 | */ 89 | public function __construct( 90 | $status = 200, 91 | array $headers = [], 92 | $body = null, 93 | $version = '1.1', 94 | $reason = null 95 | ) { 96 | if (filter_var($status, FILTER_VALIDATE_INT) === false) { 97 | throw new \InvalidArgumentException('Status code must be an integer value.'); 98 | } 99 | 100 | $this->statusCode = (int) $status; 101 | 102 | if ($body !== '' && $body !== null) { 103 | $this->stream = stream_for($body); 104 | } 105 | 106 | $this->setHeaders($headers); 107 | if ($reason == '' && isset(self::$phrases[$this->statusCode])) { 108 | $this->reasonPhrase = self::$phrases[$this->statusCode]; 109 | } else { 110 | $this->reasonPhrase = (string) $reason; 111 | } 112 | 113 | $this->protocol = $version; 114 | } 115 | 116 | public function getStatusCode() 117 | { 118 | return $this->statusCode; 119 | } 120 | 121 | public function getReasonPhrase() 122 | { 123 | return $this->reasonPhrase; 124 | } 125 | 126 | public function withStatus($code, $reasonPhrase = '') 127 | { 128 | $new = clone $this; 129 | $new->statusCode = (int) $code; 130 | if ($reasonPhrase == '' && isset(self::$phrases[$new->statusCode])) { 131 | $reasonPhrase = self::$phrases[$new->statusCode]; 132 | } 133 | $new->reasonPhrase = $reasonPhrase; 134 | return $new; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/psr7/src/Rfc7230.php: -------------------------------------------------------------------------------- 1 | @,;:\\\"/[\]?={}\x01-\x20\x7F]++):[ \t]*+((?:[ \t]*+[\x21-\x7E\x80-\xFF]++)*+)[ \t]*+\r?\n)m"; 17 | const HEADER_FOLD_REGEX = "(\r?\n[ \t]++)"; 18 | } 19 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php: -------------------------------------------------------------------------------- 1 | stream = $stream; 18 | } 19 | 20 | /** 21 | * Magic method used to create a new stream if streams are not added in 22 | * the constructor of a decorator (e.g., LazyOpenStream). 23 | * 24 | * @param string $name Name of the property (allows "stream" only). 25 | * 26 | * @return StreamInterface 27 | */ 28 | public function __get($name) 29 | { 30 | if ($name == 'stream') { 31 | $this->stream = $this->createStream(); 32 | return $this->stream; 33 | } 34 | 35 | throw new \UnexpectedValueException("$name not found on class"); 36 | } 37 | 38 | public function __toString() 39 | { 40 | try { 41 | if ($this->isSeekable()) { 42 | $this->seek(0); 43 | } 44 | return $this->getContents(); 45 | } catch (\Exception $e) { 46 | // Really, PHP? https://bugs.php.net/bug.php?id=53648 47 | trigger_error('StreamDecorator::__toString exception: ' 48 | . (string) $e, E_USER_ERROR); 49 | return ''; 50 | } 51 | } 52 | 53 | public function getContents() 54 | { 55 | return copy_to_string($this); 56 | } 57 | 58 | /** 59 | * Allow decorators to implement custom methods 60 | * 61 | * @param string $method Missing method name 62 | * @param array $args Method arguments 63 | * 64 | * @return mixed 65 | */ 66 | public function __call($method, array $args) 67 | { 68 | $result = call_user_func_array([$this->stream, $method], $args); 69 | 70 | // Always return the wrapped object if the result is a return $this 71 | return $result === $this->stream ? $this : $result; 72 | } 73 | 74 | public function close() 75 | { 76 | $this->stream->close(); 77 | } 78 | 79 | public function getMetadata($key = null) 80 | { 81 | return $this->stream->getMetadata($key); 82 | } 83 | 84 | public function detach() 85 | { 86 | return $this->stream->detach(); 87 | } 88 | 89 | public function getSize() 90 | { 91 | return $this->stream->getSize(); 92 | } 93 | 94 | public function eof() 95 | { 96 | return $this->stream->eof(); 97 | } 98 | 99 | public function tell() 100 | { 101 | return $this->stream->tell(); 102 | } 103 | 104 | public function isReadable() 105 | { 106 | return $this->stream->isReadable(); 107 | } 108 | 109 | public function isWritable() 110 | { 111 | return $this->stream->isWritable(); 112 | } 113 | 114 | public function isSeekable() 115 | { 116 | return $this->stream->isSeekable(); 117 | } 118 | 119 | public function rewind() 120 | { 121 | $this->seek(0); 122 | } 123 | 124 | public function seek($offset, $whence = SEEK_SET) 125 | { 126 | $this->stream->seek($offset, $whence); 127 | } 128 | 129 | public function read($length) 130 | { 131 | return $this->stream->read($length); 132 | } 133 | 134 | public function write($string) 135 | { 136 | return $this->stream->write($string); 137 | } 138 | 139 | /** 140 | * Implement in subclasses to dynamically create streams when requested. 141 | * 142 | * @return StreamInterface 143 | * @throws \BadMethodCallException 144 | */ 145 | protected function createStream() 146 | { 147 | throw new \BadMethodCallException('Not implemented'); 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/psr7/src/StreamWrapper.php: -------------------------------------------------------------------------------- 1 | isReadable()) { 33 | $mode = $stream->isWritable() ? 'r+' : 'r'; 34 | } elseif ($stream->isWritable()) { 35 | $mode = 'w'; 36 | } else { 37 | throw new \InvalidArgumentException('The stream must be readable, ' 38 | . 'writable, or both.'); 39 | } 40 | 41 | return fopen('guzzle://stream', $mode, null, self::createStreamContext($stream)); 42 | } 43 | 44 | /** 45 | * Creates a stream context that can be used to open a stream as a php stream resource. 46 | * 47 | * @param StreamInterface $stream 48 | * 49 | * @return resource 50 | */ 51 | public static function createStreamContext(StreamInterface $stream) 52 | { 53 | return stream_context_create([ 54 | 'guzzle' => ['stream' => $stream] 55 | ]); 56 | } 57 | 58 | /** 59 | * Registers the stream wrapper if needed 60 | */ 61 | public static function register() 62 | { 63 | if (!in_array('guzzle', stream_get_wrappers())) { 64 | stream_wrapper_register('guzzle', __CLASS__); 65 | } 66 | } 67 | 68 | public function stream_open($path, $mode, $options, &$opened_path) 69 | { 70 | $options = stream_context_get_options($this->context); 71 | 72 | if (!isset($options['guzzle']['stream'])) { 73 | return false; 74 | } 75 | 76 | $this->mode = $mode; 77 | $this->stream = $options['guzzle']['stream']; 78 | 79 | return true; 80 | } 81 | 82 | public function stream_read($count) 83 | { 84 | return $this->stream->read($count); 85 | } 86 | 87 | public function stream_write($data) 88 | { 89 | return (int) $this->stream->write($data); 90 | } 91 | 92 | public function stream_tell() 93 | { 94 | return $this->stream->tell(); 95 | } 96 | 97 | public function stream_eof() 98 | { 99 | return $this->stream->eof(); 100 | } 101 | 102 | public function stream_seek($offset, $whence) 103 | { 104 | $this->stream->seek($offset, $whence); 105 | 106 | return true; 107 | } 108 | 109 | public function stream_cast($cast_as) 110 | { 111 | $stream = clone($this->stream); 112 | 113 | return $stream->detach(); 114 | } 115 | 116 | public function stream_stat() 117 | { 118 | static $modeMap = [ 119 | 'r' => 33060, 120 | 'rb' => 33060, 121 | 'r+' => 33206, 122 | 'w' => 33188, 123 | 'wb' => 33188 124 | ]; 125 | 126 | return [ 127 | 'dev' => 0, 128 | 'ino' => 0, 129 | 'mode' => $modeMap[$this->mode], 130 | 'nlink' => 0, 131 | 'uid' => 0, 132 | 'gid' => 0, 133 | 'rdev' => 0, 134 | 'size' => $this->stream->getSize() ?: 0, 135 | 'atime' => 0, 136 | 'mtime' => 0, 137 | 'ctime' => 0, 138 | 'blksize' => 0, 139 | 'blocks' => 0 140 | ]; 141 | } 142 | 143 | public function url_stat($path, $flags) 144 | { 145 | return [ 146 | 'dev' => 0, 147 | 'ino' => 0, 148 | 'mode' => 0, 149 | 'nlink' => 0, 150 | 'uid' => 0, 151 | 'gid' => 0, 152 | 'rdev' => 0, 153 | 'size' => 0, 154 | 'atime' => 0, 155 | 'mtime' => 0, 156 | 'ctime' => 0, 157 | 'blksize' => 0, 158 | 'blocks' => 0 159 | ]; 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /vendor/guzzlehttp/psr7/src/functions_include.php: -------------------------------------------------------------------------------- 1 | 11 | * @license MIT https://opensource.org/licenses/MIT 12 | * @link dev.mailjet.com 13 | */ 14 | 15 | namespace Mailjet; 16 | 17 | class Config 18 | { 19 | const WRAPPER_VERSION = 'v1.4.1'; 20 | const USER_AGENT = 'mailjet-apiv3-php/'; 21 | const MAIN_VERSION = 'v3'; 22 | const MAIN_URL = "api.mailjet.com"; 23 | const SECURED = true; 24 | const SMS_VERSION = 'v4'; 25 | } 26 | -------------------------------------------------------------------------------- /vendor/mailjet/mailjet-apiv3-php/src/Mailjet/Request.php: -------------------------------------------------------------------------------- 1 | 11 | * @license MIT https://opensource.org/licenses/MIT 12 | * @link dev.mailjet.com 13 | */ 14 | 15 | namespace Mailjet; 16 | 17 | use GuzzleHttp\Client as GuzzleClient; 18 | use GuzzleHttp\Exception\ClientException; 19 | use GuzzleHttp\Exception\ServerException; 20 | 21 | class Request extends GuzzleClient { 22 | 23 | private $method; 24 | private $url; 25 | private $filters; 26 | private $body; 27 | private $auth; 28 | private $type; 29 | private $requestOptions = []; 30 | 31 | /** 32 | * Build a new Http request 33 | * @param array $auth [apikey, apisecret] 34 | * @param string $method http method 35 | * @param string $url call url 36 | * @param array $filters Mailjet resource filters 37 | * @param array $body Mailjet resource body 38 | * @param string $type Request Content-type 39 | */ 40 | public function __construct($auth, $method, $url, $filters, $body, $type, array $requestOptions = []) { 41 | parent::__construct(['defaults' => [ 42 | 'headers' => [ 43 | 'user-agent' => Config::USER_AGENT . phpversion() . '/' . Client::WRAPPER_VERSION 44 | ] 45 | ]]); 46 | $this->type = $type; 47 | $this->auth = $auth; 48 | $this->method = $method; 49 | $this->url = $url; 50 | $this->filters = $filters; 51 | $this->body = $body; 52 | $this->requestOptions = $requestOptions; 53 | } 54 | 55 | /** 56 | * Trigger the actual call 57 | * TODO: DATA API 58 | * @param $call 59 | * @return Response the call response 60 | */ 61 | public function call($call) { 62 | $payload = [ 63 | 'query' => $this->filters, 64 | ($this->type === 'application/json' ? 'json' : 'body') => $this->body, 65 | ]; 66 | 67 | $authArgsCount = count($this->auth); 68 | $headers = [ 69 | 'content-type' => $this->type 70 | ]; 71 | 72 | if ($authArgsCount > 1) { 73 | $payload['auth'] = $this->auth; 74 | } else { 75 | $headers['Authorization'] = 'Bearer ' . $this->auth[0]; 76 | } 77 | 78 | $payload['headers'] = $headers; 79 | 80 | if ((! empty($this->requestOptions)) && (is_array($this->requestOptions))) { 81 | $payload = array_merge_recursive($payload, $this->requestOptions); 82 | } 83 | 84 | $response = null; 85 | if ($call) { 86 | try { 87 | $response = call_user_func_array( 88 | [$this, strtolower($this->method)], [$this->url, $payload] 89 | ); 90 | } catch (ClientException $e) { 91 | $response = $e->getResponse(); 92 | } catch (ServerException $e) { 93 | $response = $e->getResponse(); 94 | } 95 | } 96 | return new Response($this, $response); 97 | } 98 | 99 | /** 100 | * Filters getters 101 | * @return array Request filters 102 | */ 103 | public function getFilters() { 104 | return $this->filters; 105 | } 106 | 107 | /** 108 | * Http method getter 109 | * @return string Request method 110 | */ 111 | public function getMethod() { 112 | return $this->method; 113 | } 114 | 115 | /** 116 | * Call Url getter 117 | * @return string Request Url 118 | */ 119 | public function getUrl() { 120 | return $this->url; 121 | } 122 | 123 | /** 124 | * Request body getter 125 | * @return array request body 126 | */ 127 | public function getBody() { 128 | return $this->body; 129 | } 130 | 131 | /** 132 | * Auth getter. to discuss 133 | * @return string Request auth 134 | */ 135 | public function getAuth() { 136 | return $this->auth; 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /vendor/mailjet/mailjet-apiv3-php/src/Mailjet/Response.php: -------------------------------------------------------------------------------- 1 | 10 | * @license https://opensource.org/licenses/MIT 11 | * @link dev.mailjet.com 12 | */ 13 | 14 | namespace Mailjet; 15 | use Psr\Http\Message\ResponseInterface; 16 | 17 | class Response 18 | { 19 | private $status; 20 | private $success; 21 | private $body; 22 | private $rawResponse; 23 | 24 | /** 25 | * Construct a Mailjet response 26 | * @param Request $request Mailjet actual request 27 | * @param ResponseInterface $response Guzzle response 28 | */ 29 | public function __construct($request, $response) 30 | { 31 | $this->request = $request; 32 | 33 | if ($response) { 34 | $this->rawResponse = $response; 35 | $this->status = $response->getStatusCode(); 36 | $this->body = $this->decodeBody($response->getBody()); 37 | $this->success = floor($this->status / 100) == 2 ? true : false; 38 | } 39 | } 40 | 41 | /** 42 | * Status Getter 43 | * return the http status code 44 | * @return int status 45 | */ 46 | public function getStatus() 47 | { 48 | return $this->status; 49 | } 50 | 51 | /** 52 | * Status Getter 53 | * return the entire response array 54 | * @return array 55 | */ 56 | public function getBody() 57 | { 58 | return $this->body; 59 | } 60 | 61 | /** 62 | * Data Getter 63 | * The data returned by the mailjet call 64 | * @return array data 65 | */ 66 | public function getData() 67 | { 68 | if (isset($this->body['Data'])) { 69 | return $this->body['Data']; 70 | } 71 | 72 | return $this->body; 73 | } 74 | 75 | /** 76 | * Count getter 77 | * return the resulting array size 78 | * @return null|int 79 | */ 80 | public function getCount() 81 | { 82 | if (isset($this->body['Count'])) { 83 | return $this->body['Count']; 84 | } 85 | 86 | return null; 87 | } 88 | 89 | /** 90 | * Error Reason getter 91 | * return the resulting error message 92 | * @return null|string 93 | */ 94 | public function getReasonPhrase() 95 | { 96 | return $this->rawResponse->getReasonPhrase(); 97 | } 98 | 99 | /** 100 | * Total getter 101 | * return the total count of all results 102 | * @return int count 103 | */ 104 | public function getTotal() 105 | { 106 | if (isset($this->body['Total'])) { 107 | return $this->body['Total']; 108 | } 109 | 110 | return null; 111 | } 112 | 113 | /** 114 | * Success getter 115 | * @return boolean true is return code is 2** 116 | */ 117 | public function success() 118 | { 119 | return $this->success; 120 | } 121 | 122 | /** 123 | * From http://stackoverflow.com/questions/19520487/json-bigint-as-string-removed-in-php-5-5 124 | * 125 | * Decodes a mailjet string response to an object reprensenting that response 126 | * 127 | * @param string $body The mailjet response as string 128 | * 129 | * @return object Object representing the mailjet response 130 | */ 131 | protected function decodeBody($body) 132 | { 133 | if (version_compare(PHP_VERSION, '5.4.0', '>=') && !(defined('JSON_C_VERSION') && PHP_INT_SIZE > 4)) { 134 | /** In PHP >=5.4.0, json_decode() accepts an options parameter, that allows you 135 | * to specify that large ints (like Steam Transaction IDs) should be treated as 136 | * strings, rather than the PHP default behaviour of converting them to floats. 137 | */ 138 | $object = json_decode($body, true, 512, JSON_BIGINT_AS_STRING); 139 | } else { 140 | /** Not all servers will support that, however, so for older versions we must 141 | * manually detect large ints in the JSON string and quote them (thus converting 142 | *them to strings) before decoding, hence the preg_replace() call. 143 | */ 144 | $maxIntLength = strlen((string) PHP_INT_MAX) - 1; 145 | $jsonWithoutBigIntegers = preg_replace('/:\s*(-?\d{'.$maxIntLength.',})/', ': "$1"', $body); 146 | $object = json_decode($jsonWithoutBigIntegers, true); 147 | } 148 | return $object; 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /vendor/mustache/mustache/src/Mustache/Autoloader.php: -------------------------------------------------------------------------------- 1 | baseDir = $realDir; 42 | } else { 43 | $this->baseDir = $baseDir; 44 | } 45 | } 46 | 47 | /** 48 | * Register a new instance as an SPL autoloader. 49 | * 50 | * @param string $baseDir Mustache library base directory (default: dirname(__FILE__).'/..') 51 | * 52 | * @return Mustache_Autoloader Registered Autoloader instance 53 | */ 54 | public static function register($baseDir = null) 55 | { 56 | $key = $baseDir ? $baseDir : 0; 57 | 58 | if (!isset(self::$instances[$key])) { 59 | self::$instances[$key] = new self($baseDir); 60 | } 61 | 62 | $loader = self::$instances[$key]; 63 | spl_autoload_register(array($loader, 'autoload')); 64 | 65 | return $loader; 66 | } 67 | 68 | /** 69 | * Autoload Mustache classes. 70 | * 71 | * @param string $class 72 | */ 73 | public function autoload($class) 74 | { 75 | if ($class[0] === '\\') { 76 | $class = substr($class, 1); 77 | } 78 | 79 | if (strpos($class, 'Mustache') !== 0) { 80 | return; 81 | } 82 | 83 | $file = sprintf('%s/%s.php', $this->baseDir, str_replace('_', '/', $class)); 84 | if (is_file($file)) { 85 | require $file; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /vendor/mustache/mustache/src/Mustache/Cache.php: -------------------------------------------------------------------------------- 1 | logger; 31 | } 32 | 33 | /** 34 | * Set a logger instance. 35 | * 36 | * @param Mustache_Logger|Psr\Log\LoggerInterface $logger 37 | */ 38 | public function setLogger($logger = null) 39 | { 40 | if ($logger !== null && !($logger instanceof Mustache_Logger || is_a($logger, 'Psr\\Log\\LoggerInterface'))) { 41 | throw new Mustache_Exception_InvalidArgumentException('Expected an instance of Mustache_Logger or Psr\\Log\\LoggerInterface.'); 42 | } 43 | 44 | $this->logger = $logger; 45 | } 46 | 47 | /** 48 | * Add a log record if logging is enabled. 49 | * 50 | * @param int $level The logging level 51 | * @param string $message The log message 52 | * @param array $context The log context 53 | */ 54 | protected function log($level, $message, array $context = array()) 55 | { 56 | if (isset($this->logger)) { 57 | $this->logger->log($level, $message, $context); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /vendor/mustache/mustache/src/Mustache/Cache/NoopCache.php: -------------------------------------------------------------------------------- 1 | log( 41 | Mustache_Logger::WARNING, 42 | 'Template cache disabled, evaluating "{className}" class at runtime', 43 | array('className' => $key) 44 | ); 45 | eval('?>' . $value); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /vendor/mustache/mustache/src/Mustache/Exception.php: -------------------------------------------------------------------------------- 1 | token = $token; 27 | if (version_compare(PHP_VERSION, '5.3.0', '>=')) { 28 | parent::__construct($msg, 0, $previous); 29 | } else { 30 | parent::__construct($msg); // @codeCoverageIgnore 31 | } 32 | } 33 | 34 | /** 35 | * @return array 36 | */ 37 | public function getToken() 38 | { 39 | return $this->token; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /vendor/mustache/mustache/src/Mustache/Exception/UnknownFilterException.php: -------------------------------------------------------------------------------- 1 | filterName = $filterName; 26 | $message = sprintf('Unknown filter: %s', $filterName); 27 | if (version_compare(PHP_VERSION, '5.3.0', '>=')) { 28 | parent::__construct($message, 0, $previous); 29 | } else { 30 | parent::__construct($message); // @codeCoverageIgnore 31 | } 32 | } 33 | 34 | public function getFilterName() 35 | { 36 | return $this->filterName; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /vendor/mustache/mustache/src/Mustache/Exception/UnknownHelperException.php: -------------------------------------------------------------------------------- 1 | helperName = $helperName; 26 | $message = sprintf('Unknown helper: %s', $helperName); 27 | if (version_compare(PHP_VERSION, '5.3.0', '>=')) { 28 | parent::__construct($message, 0, $previous); 29 | } else { 30 | parent::__construct($message); // @codeCoverageIgnore 31 | } 32 | } 33 | 34 | public function getHelperName() 35 | { 36 | return $this->helperName; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /vendor/mustache/mustache/src/Mustache/Exception/UnknownTemplateException.php: -------------------------------------------------------------------------------- 1 | templateName = $templateName; 26 | $message = sprintf('Unknown template: %s', $templateName); 27 | if (version_compare(PHP_VERSION, '5.3.0', '>=')) { 28 | parent::__construct($message, 0, $previous); 29 | } else { 30 | parent::__construct($message); // @codeCoverageIgnore 31 | } 32 | } 33 | 34 | public function getTemplateName() 35 | { 36 | return $this->templateName; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /vendor/mustache/mustache/src/Mustache/HelperCollection.php: -------------------------------------------------------------------------------- 1 | $helper` pairs. 23 | * 24 | * @throws Mustache_Exception_InvalidArgumentException if the $helpers argument isn't an array or Traversable 25 | * 26 | * @param array|Traversable $helpers (default: null) 27 | */ 28 | public function __construct($helpers = null) 29 | { 30 | if ($helpers === null) { 31 | return; 32 | } 33 | 34 | if (!is_array($helpers) && !$helpers instanceof Traversable) { 35 | throw new Mustache_Exception_InvalidArgumentException('HelperCollection constructor expects an array of helpers'); 36 | } 37 | 38 | foreach ($helpers as $name => $helper) { 39 | $this->add($name, $helper); 40 | } 41 | } 42 | 43 | /** 44 | * Magic mutator. 45 | * 46 | * @see Mustache_HelperCollection::add 47 | * 48 | * @param string $name 49 | * @param mixed $helper 50 | */ 51 | public function __set($name, $helper) 52 | { 53 | $this->add($name, $helper); 54 | } 55 | 56 | /** 57 | * Add a helper to this collection. 58 | * 59 | * @param string $name 60 | * @param mixed $helper 61 | */ 62 | public function add($name, $helper) 63 | { 64 | $this->helpers[$name] = $helper; 65 | } 66 | 67 | /** 68 | * Magic accessor. 69 | * 70 | * @see Mustache_HelperCollection::get 71 | * 72 | * @param string $name 73 | * 74 | * @return mixed Helper 75 | */ 76 | public function __get($name) 77 | { 78 | return $this->get($name); 79 | } 80 | 81 | /** 82 | * Get a helper by name. 83 | * 84 | * @throws Mustache_Exception_UnknownHelperException If helper does not exist 85 | * 86 | * @param string $name 87 | * 88 | * @return mixed Helper 89 | */ 90 | public function get($name) 91 | { 92 | if (!$this->has($name)) { 93 | throw new Mustache_Exception_UnknownHelperException($name); 94 | } 95 | 96 | return $this->helpers[$name]; 97 | } 98 | 99 | /** 100 | * Magic isset(). 101 | * 102 | * @see Mustache_HelperCollection::has 103 | * 104 | * @param string $name 105 | * 106 | * @return bool True if helper is present 107 | */ 108 | public function __isset($name) 109 | { 110 | return $this->has($name); 111 | } 112 | 113 | /** 114 | * Check whether a given helper is present in the collection. 115 | * 116 | * @param string $name 117 | * 118 | * @return bool True if helper is present 119 | */ 120 | public function has($name) 121 | { 122 | return array_key_exists($name, $this->helpers); 123 | } 124 | 125 | /** 126 | * Magic unset(). 127 | * 128 | * @see Mustache_HelperCollection::remove 129 | * 130 | * @param string $name 131 | */ 132 | public function __unset($name) 133 | { 134 | $this->remove($name); 135 | } 136 | 137 | /** 138 | * Check whether a given helper is present in the collection. 139 | * 140 | * @throws Mustache_Exception_UnknownHelperException if the requested helper is not present 141 | * 142 | * @param string $name 143 | */ 144 | public function remove($name) 145 | { 146 | if (!$this->has($name)) { 147 | throw new Mustache_Exception_UnknownHelperException($name); 148 | } 149 | 150 | unset($this->helpers[$name]); 151 | } 152 | 153 | /** 154 | * Clear the helper collection. 155 | * 156 | * Removes all helpers from this collection 157 | */ 158 | public function clear() 159 | { 160 | $this->helpers = array(); 161 | } 162 | 163 | /** 164 | * Check whether the helper collection is empty. 165 | * 166 | * @return bool True if the collection is empty 167 | */ 168 | public function isEmpty() 169 | { 170 | return empty($this->helpers); 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /vendor/mustache/mustache/src/Mustache/LambdaHelper.php: -------------------------------------------------------------------------------- 1 | =}}`. (default: null) 31 | */ 32 | public function __construct(Mustache_Engine $mustache, Mustache_Context $context, $delims = null) 33 | { 34 | $this->mustache = $mustache; 35 | $this->context = $context; 36 | $this->delims = $delims; 37 | } 38 | 39 | /** 40 | * Render a string as a Mustache template with the current rendering context. 41 | * 42 | * @param string $string 43 | * 44 | * @return string Rendered template 45 | */ 46 | public function render($string) 47 | { 48 | return $this->mustache 49 | ->loadLambda((string) $string, $this->delims) 50 | ->renderInternal($this->context); 51 | } 52 | 53 | /** 54 | * Render a string as a Mustache template with the current rendering context. 55 | * 56 | * @param string $string 57 | * 58 | * @return string Rendered template 59 | */ 60 | public function __invoke($string) 61 | { 62 | return $this->render($string); 63 | } 64 | 65 | /** 66 | * Get a Lambda Helper with custom delimiters. 67 | * 68 | * @param string $delims Custom delimiters, in the format `{{= <% %> =}}` 69 | * 70 | * @return Mustache_LambdaHelper 71 | */ 72 | public function withDelimiters($delims) 73 | { 74 | return new self($this->mustache, $this->context, $delims); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /vendor/mustache/mustache/src/Mustache/Loader.php: -------------------------------------------------------------------------------- 1 | '{{ bar }}', 19 | * 'baz' => 'Hey {{ qux }}!' 20 | * ); 21 | * 22 | * $tpl = $loader->load('foo'); // '{{ bar }}' 23 | * 24 | * The ArrayLoader is used internally as a partials loader by Mustache_Engine instance when an array of partials 25 | * is set. It can also be used as a quick-and-dirty Template loader. 26 | */ 27 | class Mustache_Loader_ArrayLoader implements Mustache_Loader, Mustache_Loader_MutableLoader 28 | { 29 | private $templates; 30 | 31 | /** 32 | * ArrayLoader constructor. 33 | * 34 | * @param array $templates Associative array of Template source (default: array()) 35 | */ 36 | public function __construct(array $templates = array()) 37 | { 38 | $this->templates = $templates; 39 | } 40 | 41 | /** 42 | * Load a Template. 43 | * 44 | * @throws Mustache_Exception_UnknownTemplateException If a template file is not found 45 | * 46 | * @param string $name 47 | * 48 | * @return string Mustache Template source 49 | */ 50 | public function load($name) 51 | { 52 | if (!isset($this->templates[$name])) { 53 | throw new Mustache_Exception_UnknownTemplateException($name); 54 | } 55 | 56 | return $this->templates[$name]; 57 | } 58 | 59 | /** 60 | * Set an associative array of Template sources for this loader. 61 | * 62 | * @param array $templates 63 | */ 64 | public function setTemplates(array $templates) 65 | { 66 | $this->templates = $templates; 67 | } 68 | 69 | /** 70 | * Set a Template source by name. 71 | * 72 | * @param string $name 73 | * @param string $template Mustache Template source 74 | */ 75 | public function setTemplate($name, $template) 76 | { 77 | $this->templates[$name] = $template; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /vendor/mustache/mustache/src/Mustache/Loader/CascadingLoader.php: -------------------------------------------------------------------------------- 1 | loaders = array(); 33 | foreach ($loaders as $loader) { 34 | $this->addLoader($loader); 35 | } 36 | } 37 | 38 | /** 39 | * Add a Loader instance. 40 | * 41 | * @param Mustache_Loader $loader 42 | */ 43 | public function addLoader(Mustache_Loader $loader) 44 | { 45 | $this->loaders[] = $loader; 46 | } 47 | 48 | /** 49 | * Load a Template by name. 50 | * 51 | * @throws Mustache_Exception_UnknownTemplateException If a template file is not found 52 | * 53 | * @param string $name 54 | * 55 | * @return string Mustache Template source 56 | */ 57 | public function load($name) 58 | { 59 | foreach ($this->loaders as $loader) { 60 | try { 61 | return $loader->load($name); 62 | } catch (Mustache_Exception_UnknownTemplateException $e) { 63 | // do nothing, check the next loader. 64 | } 65 | } 66 | 67 | throw new Mustache_Exception_UnknownTemplateException($name); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /vendor/mustache/mustache/src/Mustache/Loader/InlineLoader.php: -------------------------------------------------------------------------------- 1 | load('hello'); 20 | * $goodbye = $loader->load('goodbye'); 21 | * 22 | * __halt_compiler(); 23 | * 24 | * @@ hello 25 | * Hello, {{ planet }}! 26 | * 27 | * @@ goodbye 28 | * Goodbye, cruel {{ planet }} 29 | * 30 | * Templates are deliniated by lines containing only `@@ name`. 31 | * 32 | * The InlineLoader is well-suited to micro-frameworks such as Silex: 33 | * 34 | * $app->register(new MustacheServiceProvider, array( 35 | * 'mustache.loader' => new Mustache_Loader_InlineLoader(__FILE__, __COMPILER_HALT_OFFSET__) 36 | * )); 37 | * 38 | * $app->get('/{name}', function ($name) use ($app) { 39 | * return $app['mustache']->render('hello', compact('name')); 40 | * }) 41 | * ->value('name', 'world'); 42 | * 43 | * // ... 44 | * 45 | * __halt_compiler(); 46 | * 47 | * @@ hello 48 | * Hello, {{ name }}! 49 | */ 50 | class Mustache_Loader_InlineLoader implements Mustache_Loader 51 | { 52 | protected $fileName; 53 | protected $offset; 54 | protected $templates; 55 | 56 | /** 57 | * The InlineLoader requires a filename and offset to process templates. 58 | * 59 | * The magic constants `__FILE__` and `__COMPILER_HALT_OFFSET__` are usually 60 | * perfectly suited to the job: 61 | * 62 | * $loader = new Mustache_Loader_InlineLoader(__FILE__, __COMPILER_HALT_OFFSET__); 63 | * 64 | * Note that this only works if the loader is instantiated inside the same 65 | * file as the inline templates. If the templates are located in another 66 | * file, it would be necessary to manually specify the filename and offset. 67 | * 68 | * @param string $fileName The file to parse for inline templates 69 | * @param int $offset A string offset for the start of the templates. 70 | * This usually coincides with the `__halt_compiler` 71 | * call, and the `__COMPILER_HALT_OFFSET__` 72 | */ 73 | public function __construct($fileName, $offset) 74 | { 75 | if (!is_file($fileName)) { 76 | throw new Mustache_Exception_InvalidArgumentException('InlineLoader expects a valid filename.'); 77 | } 78 | 79 | if (!is_int($offset) || $offset < 0) { 80 | throw new Mustache_Exception_InvalidArgumentException('InlineLoader expects a valid file offset.'); 81 | } 82 | 83 | $this->fileName = $fileName; 84 | $this->offset = $offset; 85 | } 86 | 87 | /** 88 | * Load a Template by name. 89 | * 90 | * @throws Mustache_Exception_UnknownTemplateException If a template file is not found 91 | * 92 | * @param string $name 93 | * 94 | * @return string Mustache Template source 95 | */ 96 | public function load($name) 97 | { 98 | $this->loadTemplates(); 99 | 100 | if (!array_key_exists($name, $this->templates)) { 101 | throw new Mustache_Exception_UnknownTemplateException($name); 102 | } 103 | 104 | return $this->templates[$name]; 105 | } 106 | 107 | /** 108 | * Parse and load templates from the end of a source file. 109 | */ 110 | protected function loadTemplates() 111 | { 112 | if ($this->templates === null) { 113 | $this->templates = array(); 114 | $data = file_get_contents($this->fileName, false, null, $this->offset); 115 | foreach (preg_split("/^@@(?= [\w\d\.]+$)/m", $data, -1) as $chunk) { 116 | if (trim($chunk)) { 117 | list($name, $content) = explode("\n", $chunk, 2); 118 | $this->templates[trim($name)] = trim($content); 119 | } 120 | } 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /vendor/mustache/mustache/src/Mustache/Loader/MutableLoader.php: -------------------------------------------------------------------------------- 1 | '.ms', 31 | * 'stat_props' => array('size', 'mtime'), 32 | * ); 33 | * 34 | * Specifying 'stat_props' overrides the stat properties used to invalidate the template cache. By default, this 35 | * uses 'mtime' and 'size', but this can be set to any of the properties supported by stat(): 36 | * 37 | * http://php.net/manual/en/function.stat.php 38 | * 39 | * You can also disable filesystem stat entirely: 40 | * 41 | * $options = array('stat_props' => null); 42 | * 43 | * But with great power comes great responsibility. Namely, if you disable stat-based cache invalidation, 44 | * YOU MUST CLEAR THE TEMPLATE CACHE YOURSELF when your templates change. Make it part of your build or deploy 45 | * process so you don't forget! 46 | * 47 | * @throws Mustache_Exception_RuntimeException if $baseDir does not exist. 48 | * 49 | * @param string $baseDir Base directory containing Mustache template files. 50 | * @param array $options Array of Loader options (default: array()) 51 | */ 52 | public function __construct($baseDir, array $options = array()) 53 | { 54 | parent::__construct($baseDir, $options); 55 | 56 | if (array_key_exists('stat_props', $options)) { 57 | if (empty($options['stat_props'])) { 58 | $this->statProps = array(); 59 | } else { 60 | $this->statProps = $options['stat_props']; 61 | } 62 | } else { 63 | $this->statProps = array('size', 'mtime'); 64 | } 65 | } 66 | 67 | /** 68 | * Helper function for loading a Mustache file by name. 69 | * 70 | * @throws Mustache_Exception_UnknownTemplateException If a template file is not found. 71 | * 72 | * @param string $name 73 | * 74 | * @return Mustache_Source Mustache Template source 75 | */ 76 | protected function loadFile($name) 77 | { 78 | $fileName = $this->getFileName($name); 79 | 80 | if (!file_exists($fileName)) { 81 | throw new Mustache_Exception_UnknownTemplateException($name); 82 | } 83 | 84 | return new Mustache_Source_FilesystemSource($fileName, $this->statProps); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /vendor/mustache/mustache/src/Mustache/Loader/StringLoader.php: -------------------------------------------------------------------------------- 1 | load('{{ foo }}'); // '{{ foo }}' 19 | * 20 | * This is the default Template Loader instance used by Mustache: 21 | * 22 | * $m = new Mustache; 23 | * $tpl = $m->loadTemplate('{{ foo }}'); 24 | * echo $tpl->render(array('foo' => 'bar')); // "bar" 25 | */ 26 | class Mustache_Loader_StringLoader implements Mustache_Loader 27 | { 28 | /** 29 | * Load a Template by source. 30 | * 31 | * @param string $name Mustache Template source 32 | * 33 | * @return string Mustache Template source 34 | */ 35 | public function load($name) 36 | { 37 | return $name; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /vendor/mustache/mustache/src/Mustache/Logger.php: -------------------------------------------------------------------------------- 1 | log(Mustache_Logger::EMERGENCY, $message, $context); 32 | } 33 | 34 | /** 35 | * Action must be taken immediately. 36 | * 37 | * Example: Entire website down, database unavailable, etc. This should 38 | * trigger the SMS alerts and wake you up. 39 | * 40 | * @param string $message 41 | * @param array $context 42 | */ 43 | public function alert($message, array $context = array()) 44 | { 45 | $this->log(Mustache_Logger::ALERT, $message, $context); 46 | } 47 | 48 | /** 49 | * Critical conditions. 50 | * 51 | * Example: Application component unavailable, unexpected exception. 52 | * 53 | * @param string $message 54 | * @param array $context 55 | */ 56 | public function critical($message, array $context = array()) 57 | { 58 | $this->log(Mustache_Logger::CRITICAL, $message, $context); 59 | } 60 | 61 | /** 62 | * Runtime errors that do not require immediate action but should typically 63 | * be logged and monitored. 64 | * 65 | * @param string $message 66 | * @param array $context 67 | */ 68 | public function error($message, array $context = array()) 69 | { 70 | $this->log(Mustache_Logger::ERROR, $message, $context); 71 | } 72 | 73 | /** 74 | * Exceptional occurrences that are not errors. 75 | * 76 | * Example: Use of deprecated APIs, poor use of an API, undesirable things 77 | * that are not necessarily wrong. 78 | * 79 | * @param string $message 80 | * @param array $context 81 | */ 82 | public function warning($message, array $context = array()) 83 | { 84 | $this->log(Mustache_Logger::WARNING, $message, $context); 85 | } 86 | 87 | /** 88 | * Normal but significant events. 89 | * 90 | * @param string $message 91 | * @param array $context 92 | */ 93 | public function notice($message, array $context = array()) 94 | { 95 | $this->log(Mustache_Logger::NOTICE, $message, $context); 96 | } 97 | 98 | /** 99 | * Interesting events. 100 | * 101 | * Example: User logs in, SQL logs. 102 | * 103 | * @param string $message 104 | * @param array $context 105 | */ 106 | public function info($message, array $context = array()) 107 | { 108 | $this->log(Mustache_Logger::INFO, $message, $context); 109 | } 110 | 111 | /** 112 | * Detailed debug information. 113 | * 114 | * @param string $message 115 | * @param array $context 116 | */ 117 | public function debug($message, array $context = array()) 118 | { 119 | $this->log(Mustache_Logger::DEBUG, $message, $context); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /vendor/mustache/mustache/src/Mustache/Source.php: -------------------------------------------------------------------------------- 1 | fileName = $fileName; 35 | $this->statProps = $statProps; 36 | } 37 | 38 | /** 39 | * Get the Source key (used to generate the compiled class name). 40 | * 41 | * @throws RuntimeException when a source file cannot be read 42 | * 43 | * @return string 44 | */ 45 | public function getKey() 46 | { 47 | $chunks = array( 48 | 'fileName' => $this->fileName, 49 | ); 50 | 51 | if (!empty($this->statProps)) { 52 | if (!isset($this->stat)) { 53 | $this->stat = @stat($this->fileName); 54 | } 55 | 56 | if ($this->stat === false) { 57 | throw new RuntimeException(sprintf('Failed to read source file "%s".', $this->fileName)); 58 | } 59 | 60 | foreach ($this->statProps as $prop) { 61 | $chunks[$prop] = $this->stat[$prop]; 62 | } 63 | } 64 | 65 | return json_encode($chunks); 66 | } 67 | 68 | /** 69 | * Get the template Source. 70 | * 71 | * @return string 72 | */ 73 | public function getSource() 74 | { 75 | return file_get_contents($this->fileName); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /vendor/psr/http-message/src/ResponseInterface.php: -------------------------------------------------------------------------------- 1 | 'Content-Type', 16 | 'CONTENT_LENGTH' => 'Content-Length', 17 | 'CONTENT_MD5' => 'Content-Md5', 18 | ); 19 | 20 | foreach ($_SERVER as $key => $value) { 21 | if (substr($key, 0, 5) === 'HTTP_') { 22 | $key = substr($key, 5); 23 | if (!isset($copy_server[$key]) || !isset($_SERVER[$key])) { 24 | $key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key)))); 25 | $headers[$key] = $value; 26 | } 27 | } elseif (isset($copy_server[$key])) { 28 | $headers[$copy_server[$key]] = $value; 29 | } 30 | } 31 | 32 | if (!isset($headers['Authorization'])) { 33 | if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) { 34 | $headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION']; 35 | } elseif (isset($_SERVER['PHP_AUTH_USER'])) { 36 | $basic_pass = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : ''; 37 | $headers['Authorization'] = 'Basic ' . base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $basic_pass); 38 | } elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) { 39 | $headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST']; 40 | } 41 | } 42 | 43 | return $headers; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /widgets/mailjet/mailjet.html.php: -------------------------------------------------------------------------------- 1 | 15 |
16 |
17 | 18 |
19 |
20 | 21 |
22 |
23 | -------------------------------------------------------------------------------- /widgets/mailjet/mailjet.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'text' => 'Kirby Mailjet License', 6 | 'link' => false, 7 | 'compressed' => false 8 | ], 9 | 'html' => function() { 10 | return tpl::load(__DIR__ . DS . 'mailjet.html.php', array( 11 | 'text' => 'Kirby Mailjet is running in trial mode. Please support the development of this plugin and buy a license. If you already have a license key, please add it to your config.php file.', 12 | )); 13 | } 14 | ]; 15 | --------------------------------------------------------------------------------