├── .gitignore ├── images ├── spinner.gif ├── mimi-voice.png └── spinner-2x.gif ├── wp-org-assets ├── icon-128x128.png ├── icon-256x256.png ├── screenshot-1.png ├── screenshot-2.png ├── screenshot-3.png ├── screenshot-4.png ├── banner-1544x500.png └── banner-772x250.png ├── .gitmodules ├── css ├── admin.min.css ├── admin-rtl.min.css ├── admin.css ├── admin-rtl.css ├── mimi.min.css └── mimi.css ├── .distignore ├── uninstall.php ├── includes ├── class-shortcode.php ├── widget.php ├── class-dispatcher.php ├── render.php └── settings.php ├── composer.json ├── phpcs.ruleset.xml ├── .travis.yml ├── package.json ├── js ├── mimi.min.js └── mimi.js ├── readme.txt ├── bin └── replacer.sh ├── languages └── mad-mimi-sign-up-forms.pot ├── madmimiofficial.php ├── readme.md ├── Gruntfile.js └── license.txt /.gitignore: -------------------------------------------------------------------------------- 1 | svn-username 2 | build/ 3 | node_modules/ 4 | vendor/ 5 | -------------------------------------------------------------------------------- /images/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/godaddy/madmimi-wp/master/images/spinner.gif -------------------------------------------------------------------------------- /images/mimi-voice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/godaddy/madmimi-wp/master/images/mimi-voice.png -------------------------------------------------------------------------------- /images/spinner-2x.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/godaddy/madmimi-wp/master/images/spinner-2x.gif -------------------------------------------------------------------------------- /wp-org-assets/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/godaddy/madmimi-wp/master/wp-org-assets/icon-128x128.png -------------------------------------------------------------------------------- /wp-org-assets/icon-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/godaddy/madmimi-wp/master/wp-org-assets/icon-256x256.png -------------------------------------------------------------------------------- /wp-org-assets/screenshot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/godaddy/madmimi-wp/master/wp-org-assets/screenshot-1.png -------------------------------------------------------------------------------- /wp-org-assets/screenshot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/godaddy/madmimi-wp/master/wp-org-assets/screenshot-2.png -------------------------------------------------------------------------------- /wp-org-assets/screenshot-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/godaddy/madmimi-wp/master/wp-org-assets/screenshot-3.png -------------------------------------------------------------------------------- /wp-org-assets/screenshot-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/godaddy/madmimi-wp/master/wp-org-assets/screenshot-4.png -------------------------------------------------------------------------------- /wp-org-assets/banner-1544x500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/godaddy/madmimi-wp/master/wp-org-assets/banner-1544x500.png -------------------------------------------------------------------------------- /wp-org-assets/banner-772x250.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/godaddy/madmimi-wp/master/wp-org-assets/banner-772x250.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "dev-lib"] 2 | path = dev-lib 3 | url = https://github.com/xwp/wp-dev-lib.git 4 | branch = master 5 | -------------------------------------------------------------------------------- /css/admin.min.css: -------------------------------------------------------------------------------- 1 | div.updated.mimi-identity{background-image:url( '../images/mimi-voice.png' );background-repeat:no-repeat;background-position:15px 20px;background-size:50px;padding-left:80px!important} -------------------------------------------------------------------------------- /css/admin-rtl.min.css: -------------------------------------------------------------------------------- 1 | div.updated.mimi-identity{background-image:url( '../images/mimi-voice.png' );background-repeat:no-repeat;background-position:15px 20px;background-size:50px;padding-right:80px!important} -------------------------------------------------------------------------------- /css/admin.css: -------------------------------------------------------------------------------- 1 | div.updated.mimi-identity { 2 | background-image: url( '../images/mimi-voice.png' ); 3 | background-repeat: no-repeat; 4 | background-position: 15px 20px; 5 | background-size: 50px; 6 | padding-left: 80px !important; 7 | } -------------------------------------------------------------------------------- /css/admin-rtl.css: -------------------------------------------------------------------------------- 1 | div.updated.mimi-identity { 2 | background-image: url( '../images/mimi-voice.png' ); 3 | background-repeat: no-repeat; 4 | background-position: 15px 20px; 5 | background-size: 50px; 6 | padding-right: 80px !important; 7 | } -------------------------------------------------------------------------------- /.distignore: -------------------------------------------------------------------------------- 1 | .* 2 | *.yml 3 | composer.* 4 | Gruntfile.js 5 | package.json 6 | phpcs.ruleset.xml 7 | phpunit.xml.dist 8 | readme.md 9 | svn-username 10 | bin/ 11 | build/ 12 | dev-lib/ 13 | languages/*.po 14 | node_modules/ 15 | tests/ 16 | vendor/ 17 | wp-org-assets/ 18 | -------------------------------------------------------------------------------- /uninstall.php: -------------------------------------------------------------------------------- 1 | false, 9 | ), $atts ); 10 | 11 | if ( empty( $atts['id'] ) ) { 12 | 13 | return; 14 | 15 | } 16 | 17 | return Mad_Mimi_Form_Renderer::process( $atts['id'], false ); 18 | 19 | } 20 | 21 | } 22 | 23 | /** 24 | * The main template tag. Pass on the ID and watch the magic happen. 25 | * 26 | * @since 1.0 27 | * 28 | * @see Mad_Mimi_Form_Renderer 29 | * 30 | * @param int $id The ID of the form you wish to output 31 | */ 32 | function madmimi_form( $id ) { 33 | 34 | if ( ! class_exists( 'Mad_Mimi_Form_Renderer' ) ) { 35 | 36 | return; 37 | 38 | } 39 | 40 | Mad_Mimi_Form_Renderer::process( $id, true ); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "madmimi/madmimi-wp", 3 | "description": "Add the Mad Mimi webform to your WordPress site! Easy to set up, the Mad Mimi plugin allows your site visitors to subscribe to your email lists.", 4 | "type" : "wordpress-plugin", 5 | "license" : "GPL-2.0+", 6 | "require": { 7 | "10up/wp-codeception": "^1.0" 8 | }, 9 | "extra": { 10 | "installer-paths": { 11 | "vendor/{$name}/": ["type:wordpress-plugin"] 12 | } 13 | }, 14 | "autoload": { 15 | "files": [ 16 | "vendor/wp-codeception/wp-codeception.php" 17 | ] 18 | }, 19 | "scripts": { 20 | "post-install-cmd": [ 21 | "if [ -n \"$(command -v apt-get)\" ]; then sudo apt-get install openjdk-7-jre-headless --yes || true; fi", 22 | "cd vendor/wp-codeception && npm install" 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /phpcs.ruleset.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Generally-applicable sniffs for WordPress plugins 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | */dev-lib/* 15 | */build/* 16 | */node_modules/* 17 | */tests/* 18 | */vendor/* 19 | 20 | -------------------------------------------------------------------------------- /css/mimi.css: -------------------------------------------------------------------------------- 1 | /* basic CSS styles */ 2 | 3 | /** 4 | * Fields 5 | */ 6 | 7 | form.mimi-form p { 8 | padding: 0; 9 | } 10 | 11 | input.mimi-invalid { 12 | border: 1px solid red; 13 | } 14 | 15 | .mimi-field { 16 | display: block; 17 | } 18 | 19 | .mimi-spinner { 20 | display: none; 21 | background: url( '../images/spinner.gif' ) no-repeat; 22 | background-size: 20px 20px; 23 | width: 20px; 24 | height: 20px; 25 | } 26 | 27 | .mimi-submit { 28 | cursor: pointer; 29 | } 30 | 31 | /** 32 | * Messages 33 | */ 34 | .mimi-error { 35 | background-color: #ffebe8; 36 | border: 1px solid #c00; 37 | padding: 0.5em 1em; 38 | margin: 0.6em 0; 39 | border-radius: 3px; 40 | } 41 | 42 | @media only screen and (max-width: 279px) { 43 | form.mimi-form select { 44 | margin-top: 5px; 45 | } 46 | } 47 | 48 | /** 49 | * Widgets 50 | */ 51 | .widget.mimi-form span.third { 52 | display: inline-block; 53 | } 54 | 55 | /** 56 | * HiDPI Displays 57 | */ 58 | @media print, 59 | (-o-min-device-pixel-ratio: 5/4), 60 | (-webkit-min-device-pixel-ratio: 1.25), 61 | (min-resolution: 120dpi) { 62 | 63 | .mimi-spinner { 64 | background-image: url( '../images/spinner-2x.gif' ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: php 4 | 5 | notifications: 6 | email: 7 | on_success: never 8 | on_failure: change 9 | 10 | php: 11 | - 5.6 12 | - 7.1 13 | 14 | env: 15 | - WP_VERSION=5.4 WP_MULTISITE=0 16 | - WP_VERSION=latest WP_MULTISITE=0 17 | - WP_VERSION=trunk WP_MULTISITE=0 18 | 19 | addons: 20 | apt: 21 | packages: 22 | # Needed for `xmllint`. 23 | - libxml2-utils 24 | 25 | matrix: 26 | fast_finish: true 27 | exclude: 28 | - php: 7.1 29 | env: WP_VERSION=5.4 WP_MULTISITE=0 30 | 31 | install: 32 | - export DEV_LIB_PATH=dev-lib 33 | - if [ ! -e "$DEV_LIB_PATH" ] && [ -L .travis.yml ]; then export DEV_LIB_PATH=$( dirname $( readlink .travis.yml ) ); fi 34 | - if [ ! -e "$DEV_LIB_PATH" ]; then git clone https://github.com/xwp/wp-dev-lib.git $DEV_LIB_PATH; fi 35 | - source $DEV_LIB_PATH/travis.install.sh 36 | 37 | script: 38 | - source $DEV_LIB_PATH/travis.script.sh 39 | 40 | before_deploy: 41 | - curl https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli-nightly.phar > /tmp/wp-cli.phar 42 | - chmod +x /tmp/wp-cli.phar 43 | - export RELEASE_FOLDER=mad-mimi-sign-up-forms 44 | - php /tmp/wp-cli.phar package install git@github.com:wp-cli/dist-archive-command.git 45 | - cp -r ${TRAVIS_BUILD_DIR} /tmp/${RELEASE_FOLDER} 46 | - mv /tmp/${RELEASE_FOLDER} ${TRAVIS_BUILD_DIR} 47 | - php /tmp/wp-cli.phar dist-archive ${RELEASE_FOLDER} ${TRAVIS_BUILD_DIR}/${RELEASE_FOLDER}.zip --format=zip --debug 48 | 49 | deploy: 50 | provider: releases 51 | api_key: 52 | secure: JyF51/WstXFpqMPOexhtE1o9u9Uge1xUZbSMjNaOaUcRbMkQ3WOML+WfnFo/xnLZI1puUzS8XrvhpTZll1Kot3OltRP2Z6lBp02ACh/e9cPwrFaBwy8evj977SaizdhWmzjhZqnN0vDiheyyONOc3QnUfLChR5QBhdnh8IfXSHg= 53 | file: $RELEASE_FOLDER.zip 54 | on: 55 | tags: true 56 | repo: madmimi/madmimi-wp 57 | php: '7.1' 58 | condition: "$WP_VERSION=trunk" 59 | skip_cleanup: true 60 | overwrite: true 61 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mad-mimi-sign-up-forms", 3 | "title": "Mad Mimi Sign Up Forms", 4 | "description": "Add the Mad Mimi webform to your WordPress site! Easy to set up, the Mad Mimi plugin allows your site visitors to subscribe to your email lists.", 5 | "version": "1.7.1", 6 | "author": "GoDaddy", 7 | "license": "GPL-2.0", 8 | "repository": "madmimi/madmimi-wp", 9 | "homepage": "https://wordpress.org/plugins/mad-mimi-sign-up-forms/", 10 | "bugs": { 11 | "url": "https://github.com/madmimi/madmimi-wp/issues" 12 | }, 13 | "engines": { 14 | "node": ">= 7.5.0", 15 | "php": ">= 5.4", 16 | "wordpress": ">= 4.4" 17 | }, 18 | "badges": [ 19 | "[![Build Status](https://travis-ci.org/<%= pkg.repository %>.svg?branch=master)](https://travis-ci.org/<%= pkg.repository %>)", 20 | "[![License](https://img.shields.io/badge/license-GPL--2.0-brightgreen.svg)](https://github.com/<%= pkg.repository %>/blob/master/license.txt)", 21 | "[![PHP <%= pkg.engines.php %>](https://img.shields.io/badge/php-<% print(encodeURI(pkg.engines.php)) %>-8892bf.svg)](https://secure.php.net/supported-versions.php)", 22 | "[![WordPress <%= pkg.engines.wordpress %>](https://img.shields.io/badge/wordpress-<% print(encodeURI(pkg.engines.wordpress)) %>-blue.svg)](https://wordpress.org/download/release-archive/)" 23 | ], 24 | "devDependencies": { 25 | "grunt": "^1.1.0", 26 | "grunt-contrib-clean": "^2.0.0", 27 | "grunt-contrib-copy": "^1.0.0", 28 | "grunt-contrib-cssmin": "^3.0.0", 29 | "grunt-contrib-imagemin": "^4.0.0", 30 | "grunt-contrib-jshint": "^2.1.0", 31 | "grunt-contrib-uglify": "^4.0.1", 32 | "grunt-contrib-watch": "^1.0.0", 33 | "grunt-cssjanus": "^0.5.0", 34 | "grunt-text-replace": "^0.4.0", 35 | "grunt-wp-deploy": "^2.0.0", 36 | "grunt-wp-i18n": "^1.0.3", 37 | "grunt-wp-readme-to-markdown": "^2.0.1", 38 | "matchdep": "^2.0.0" 39 | }, 40 | "scripts": { 41 | "version": "grunt version && git add -A .", 42 | "postversion": "git push && git push --tags" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /js/mimi.min.js: -------------------------------------------------------------------------------- 1 | !function(l){"use strict";var f=window.MadMimi||{};f.DEBUG_FLAG=!0,f.init=function(){l("form.mimi-form").submit(function(i){i.preventDefault();var t="",s=0,n="";l(this).find(":input").each(function(i){var e=l(this).attr("name");"checkbox"==l(this).attr("type")&&l(this).is(":checked")&&(n!=e&&(n=e,s=0),0==s&&(t=l("input:checkbox[name='"+e+"']:checked").map(function(){return this.value}).get().join(", "),s=1),l("input[name='"+e+"']").val(t))});var a="",r="",h=[];l(this).find("[fingerprint='date']").each(function(i){var e=l(this).attr("name");"date"==l(this).attr("fingerprint")&&(r!=e&&(r=e,h=[],a=""),h.push(l(this).val()),3==h.length&&(a=h[0]+" "+h[1]+", "+h[2]),l("input[name='"+e+"']").val(a))});var u=l(this),e=l(".mimi-spinner",u),o=l(this).serialize(),c=[],m=f;if(u.find("input.mimi-invalid").removeClass("mimi-invalid"),l(this).find(":input").each(function(i){"signup[email]"!=l(this).attr("name")||f.isEmail(l(this).val())?(l(this).is('input[type="checkbox"]')&&l(this).hasClass("mimi-required")&&!l(this).is(":checked")||l(this).is(".mimi-required")&&""==l(this).val())&&(c.push(l(this)),m.log("A required filled was not filled")):(c.push(l(this)),m.log("Email is NOT valid"))}),0==c.length)e.css("display","inline-block"),l.post(u.attr("action")+".json",o,function(t){u.fadeOut("fast",function(){if(t.success){var i=t.result,e=i.audience_member.suppressed;i.has_redirect&&(window.location.href=i.redirect),u.html(f.addMessage(e?["suppressed","success"]:["info","success"],e?f.thankyou_suppressed:f.thankyou)).fadeIn("fast")}else u.html(f.addMessage("info",f.oops)).fadeIn("fast")})},"jsonp");else{l(c).each(function(i,e){l(this).addClass("mimi-invalid")});var d=u.find(".mimi-error, .mimi-info");0!=d.length&&d.remove(),u.prepend(f.addMessage("error",f.fix))}})},f.addMessage=function(i,e){var t=[];return l.isArray(i)?l.each(i,function(i,e){t.push("mimi-"+e)}):t.push("mimi-"+i.toString()),l("

",{class:t.join(" ")}).text(e)},f.isEmail=function(i){return/^([a-zA-Z0-9_\.\-\+])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(i)},f.log=function(i){f.DEBUG_FLAG&&window.console&&console.log(i)},l.fn.mimiSerializeObject=function(){var i={},e=this.serializeArray();return l.each(e,function(){i[this.name]?(i[this.name].push||(i[this.name]=[i[this.name]]),i[this.name].push(this.value||"")):i[this.name]=this.value||""}),i},l(document).ready(f.init)}(jQuery); -------------------------------------------------------------------------------- /includes/widget.php: -------------------------------------------------------------------------------- 1 | 'mimi-form', 14 | 'description' => __( 'Embed any Mad Mimi webform in your sidebar.', 'mad-mimi-sign-up-forms' ), 15 | ) ); 16 | 17 | foreach ( array( 'wpautop', 'wptexturize', 'convert_chars' ) as $filter ) { 18 | 19 | add_filter( 'mimi_widget_text', $filter ); 20 | 21 | } 22 | 23 | } 24 | 25 | public function widget( $args, $instance ) { 26 | 27 | // Set the initial form ID value if one exists. 28 | if ( empty( $instance['form'] ) ) { 29 | 30 | $forms = Mad_Mimi_Dispatcher::get_forms(); 31 | 32 | if ( ! empty( $forms->signups ) ) { 33 | 34 | $instance['form'] = $forms->signups[0]->id; 35 | 36 | } 37 | 38 | } 39 | 40 | $title = apply_filters( 'widget_title', empty( $instance['title'] ) ? __( 'Mad Mimi Form', 'mad-mimi-sign-up-forms' ) : $instance['title'], $instance, $this->id_base ); 41 | $text = empty( $instance['text'] ) ? '' : $instance['text']; 42 | $form_id = empty( $instance['form'] ) ? false : $instance['form']; 43 | 44 | echo $args['before_widget']; // xss ok. 45 | 46 | if ( $title ) { 47 | 48 | echo $args['before_title'] . esc_html( $title ) . $args['after_title']; // xss ok. 49 | 50 | } 51 | 52 | if ( $text ) { 53 | 54 | echo wp_kses_post( apply_filters( 'mimi_widget_text', $text ) ); 55 | 56 | } 57 | 58 | Mad_Mimi_Form_Renderer::process( $form_id, true ); 59 | 60 | echo $args['after_widget']; // xss ok. 61 | 62 | } 63 | 64 | public function update( $new_instance, $old_instance ) { 65 | 66 | $instance = $old_instance; 67 | 68 | $instance['title'] = strip_tags( $new_instance['title'] ); 69 | $instance['text'] = $new_instance['text']; 70 | $instance['form'] = absint( $new_instance['form'] ); 71 | 72 | return $instance; 73 | 74 | } 75 | 76 | public function form( $instance ) { 77 | 78 | // set defaults 79 | $instance = wp_parse_args( (array) $instance, array( 80 | 'title' => '', 81 | 'text' => '', 82 | 'form' => 0, 83 | ) ); 84 | 85 | $forms = Mad_Mimi_Dispatcher::get_forms(); ?> 86 | 87 |

88 | 89 | 90 |

91 | 92 |

93 | 94 | 95 |

96 | 97 |

98 | 99 | signups ) ) : ?> 100 | 101 | 102 | 103 | 110 | 111 | 112 | 113 | 114 | %2$s', 121 | esc_url_raw( admin_url( 'options-general.php?page=mad-mimi-settings' ) ), 122 | esc_html__( 'settings page', 'mad-mimi-sign-up-forms' ) 123 | ) 124 | ) 125 | ); 126 | ?> 127 | 128 | 129 | 130 | 131 |

132 | 133 | Mad Mimi Settings**. 29 | 4. Enter your Mad Mimi username and API key. 30 | 5. Click **Save Settings**. 31 | 32 | After your account is verified, you can insert a form into your site by using a **widget**, **shortcode**, or **template tag** directly in your theme. See the FAQ section for more details. 33 | 34 | == Frequently Asked Questions == 35 | 36 | = What is Mad Mimi? = 37 | 38 | [Mad Mimi](https://madmimi.com) is the easiest way to create, send, share, and track email newsletters online. It's for people who want email marketing to be simple. 39 | 40 | = Do I need a Mad Mimi account to use this plugin? = 41 | 42 | Yes, this plugin requires a [Mad Mimi](https://madmimi.com) account. 43 | 44 | = Is there a widget? = 45 | 46 | Absolutely. Use it by finding the Mad Mimi Form widget under **Appearance > Widgets** in the WordPress Dashboard and dragging it into the widget area of your choice. You can then add a title and select a form! 47 | 48 | = Is there a shortcode? = 49 | 50 | Yes! You can add a form to any post or page by adding the shortcode with the form ID (e.g., `[madmimi id=123456 ]`) in the page/post editor. 51 | 52 | = Is there a template tag? = 53 | 54 | Yup! Add the following template tag into any WordPress theme template file: ``. For example: `` where `123456` is your form ID. 55 | 56 | = Where can I find my form IDs? = 57 | 58 | To find your form IDs, navigate to **Settings > Mad Mimi Settings** and scroll down to the **Available Forms** section. If you've recently created new forms click the **Refresh Forms** button to pull them into your WordPress site. 59 | 60 | = Where can I find the API Key? = 61 | 62 | Your API Key can be found in your Mad Mimi account area. For more details [see this help article](https://help.madmimi.com/where-can-i-find-my-api-key/). 63 | 64 | == Screenshots == 65 | 66 | 1. Settings screen. 67 | 2. A full list of your Mad Mimi forms, with handy shortcodes. 68 | 3. The widget on the front-end. 69 | 4. The widget on the widgets page. 70 | 71 | == Changelog == 72 | 73 | = 1.7.1 = 74 | * Fix: Resolve PHP notice. 75 | * Tweak: Test with and bump support for WordPress 5.4. 76 | 77 | = 1.7.0 = 78 | * New: Add support for GDPR fields (Age consent, terms of service and tracking option) 79 | 80 | = 1.6.0 = 81 | * New: Reference to jQuery UI has been removed. 82 | * Tweak: Styles updated for MadMimi fancy fields. 83 | * Fix: Resolved 'Mixed Content' warning when using on sites with SSL enabled. 84 | * Fix: Various code improvements. 85 | 86 | = 1.5.1 = 87 | * Fixed shortcode display. 88 | 89 | = 1.5 = 90 | * This update includes various bug fixes. 91 | 92 | = 1.4 = 93 | * Added support for web form fancy fields 94 | * Made some styling changes to mobile view 95 | 96 | = 1.3 = 97 | * Coding standards 98 | * Fixed up some improper escaping and sanitization 99 | * Updated Admin UI to more closely match default WordPress style 100 | * Minor improvements to plugin copy 101 | 102 | = 1.2 = 103 | * Fixed the padding for p tags in the mad mimi signup form 104 | 105 | = 1.1 = 106 | * New! Upon form submit, the plugin checks to see if the Mad Mimi user has specified that the new subscriber should be redirected to a specific webpage after subscribing (Confirmation Landing Page). If the user has specified a Confirmation Landing Page for their webform, the new subscriber will be redirected to that page after subscribing. 107 | * Better cache handling for the provided CSS and JS core files 108 | * Bug fixes 109 | 110 | = 1.0 = 111 | * Initial version. Hoozah! 112 | -------------------------------------------------------------------------------- /bin/replacer.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | function renameFile { 4 | sourceFile=$1 5 | find=$2 6 | replaceWith=$3 7 | saveChanges=$4 8 | targetFile=$(echo $sourceFile | sed "s/$find/$replaceWith/g") 9 | 10 | if [[ $sourceFile != $targetFile ]]; then 11 | echo "Renaming file '$sourceFile' to '$targetFile'" 12 | if [[ $saveChanges == '1' ]]; then 13 | mv "$sourceFile" "$targetFile" 14 | echo "[OK]" 15 | fi 16 | fi 17 | } 18 | 19 | function replacePHPComments { 20 | sourceFile=$1 21 | find=$2 22 | replaceWith=$3 23 | pattern=$4 24 | saveChanges=$5 25 | 26 | if [[ $sourceFile =~ $pattern ]]; then 27 | fileContentOrg="$(cat "$sourceFile")" 28 | fileContent="$(cat "$sourceFile")" 29 | fileContent=$(echo "$fileContent" |sed -e "s/\(#[^\r\n]*\)$find\([^\r\n]*\)/\1$replaceWith\2/g") 30 | fileContent=$(echo "$fileContent" |sed -e "s/\(\/\/[^\r\n]*\)$find\([^\r\n]*\)/\1$replaceWith\2/g") 31 | 32 | # multiline: 33 | fileContent=$(echo "$fileContent" |sed -e ':a;N;$!ba;s/\n/_the_new_line/g') 34 | fileContent=$(echo "$fileContent" |sed -e "s/\(\/\*.*\)$find\(.*\*\/\)/\1$replaceWith\2/g") 35 | fileContent=$(echo "$fileContent" |sed -e 's/_the_new_line/\n/g') 36 | 37 | if [[ $fileContent != $fileContentOrg ]]; then 38 | echo "[Replace in PHP comments] $sourceFile" 39 | if [[ $saveChanges == '1' ]]; then 40 | echo "$fileContent" >| $sourceFile 41 | echo "[OK]" 42 | fi 43 | fi 44 | fi 45 | } 46 | 47 | function replacePHPStrings { 48 | sourceFile=$1 49 | find=$2 50 | replaceWith=$3 51 | pattern=$4 52 | saveChanges=$5 53 | 54 | if [[ $sourceFile =~ $pattern ]]; then 55 | fileContentOrg="$(cat "$sourceFile")" 56 | fileContent="$(cat "$sourceFile")" 57 | fileContent=$(echo "$fileContent" |sed -e "s/\('[^']*\)$find/\1$replaceWith/g") 58 | fileContent=$(echo "$fileContent" |sed -e "s/\(\"[^\"]*\)$find/\1$replaceWith/g") 59 | 60 | if [[ $fileContent != $fileContentOrg ]]; then 61 | echo "[Replace in PHP strings] $sourceFile" 62 | if [[ $saveChanges == '1' ]]; then 63 | echo "$fileContent" >| $sourceFile 64 | echo "[OK]" 65 | fi 66 | fi 67 | fi 68 | } 69 | 70 | 71 | function replaceCSSSelectors { 72 | sourceFile=$1 73 | find=$2 74 | replaceWith=$3 75 | pattern=$4 76 | saveChanges=$5 77 | 78 | if [[ $sourceFile =~ $pattern ]]; then 79 | fileContentOrg="$(cat "$sourceFile")" 80 | fileContent="$(cat "$sourceFile")" 81 | 82 | fileContent=$(echo "$fileContent" |sed -e "s/\([\ \#\.\w\-\,\s\n\r\t:]*\)$find/\1$replaceWith/g") 83 | 84 | if [[ $fileContent != $fileContentOrg ]]; then 85 | echo "[Replace in CSS selectors $sourceFile" 86 | if [[ $saveChanges == '1' ]]; then 87 | echo "$fileContent" >| $sourceFile 88 | echo "[OK]" 89 | fi 90 | fi 91 | fi 92 | } 93 | 94 | function replacePHPClassNamesSelectors { 95 | sourceFile=$1 96 | find=$2 97 | replaceWith=$3 98 | pattern=$4 99 | saveChanges=$5 100 | 101 | if [[ $sourceFile =~ $pattern ]]; then 102 | fileContentOrg="$(cat "$sourceFile")" 103 | fileContent="$(cat "$sourceFile")" 104 | 105 | fileContent=$(echo "$fileContent" |sed -e "s/\(class[ \t\n]*[A-Za-z_]*\)$find/\1$replaceWith/g") 106 | 107 | if [[ $fileContent != $fileContentOrg ]]; then 108 | echo "[Replace in CSS selectors $sourceFile" 109 | if [[ $saveChanges == '1' ]]; then 110 | echo "$fileContent" >| $sourceFile 111 | echo "[OK]" 112 | fi 113 | fi 114 | fi 115 | } 116 | 117 | function replaceAllOccurrences { 118 | sourceFile=$1 119 | find=$2 120 | replaceWith=$3 121 | pattern=$4 122 | saveChanges=$5 123 | 124 | if [[ $sourceFile =~ $pattern ]]; then 125 | fileContentOrg="$(cat "$sourceFile")" 126 | fileContent="$(cat "$sourceFile")" 127 | fileContent=$(echo "$fileContent" |sed -e "s/$find/$replaceWith/g") 128 | 129 | if [[ $fileContent != $fileContentOrg ]]; then 130 | echo "Replacing all occurrences of '$find' with '$replaceWith' in $sourceFile" 131 | if [[ $saveChanges == '1' ]]; then 132 | echo "$fileContent" >| $sourceFile 133 | echo "[OK]" 134 | fi 135 | 136 | fi 137 | fi 138 | } 139 | 140 | if [ $# -eq 0 ]; then 141 | echo ">> replacer <<"; 142 | echo "By marcin-lawrowski (https://github.com/marcin-lawrowski)"; 143 | echo ""; 144 | echo "Usage: $0 path [disable-dry-run]"; 145 | echo ""; 146 | echo "path = Existing directory to perform strings replacements on"; 147 | echo "[disable-dry-run] = Use 1 value if you want to disable dry run mode"; 148 | echo ""; 149 | exit 1; 150 | fi 151 | 152 | ALLOWED_FILES_MASK="(\.php)|(\.css)|(\.js)|(\.txt)|(\.md)|(\.pot)" 153 | targetPath=$1 154 | saveChanges=$2 155 | 156 | if [ ! -d "$targetPath" ]; then 157 | echo "$targetPath directory does not exist" 158 | exit 1; 159 | fi 160 | 161 | if [[ $saveChanges != '1' ]]; then 162 | echo "Dry run mode in action" 163 | else 164 | echo "Dry run mode is disabled, all changes will be saved" 165 | fi 166 | 167 | for sourceFile in $(find "$targetPath" -not \( -path "$targetPath/dev-lib/*" -o -path "$targetPath/.git/*" \)); do 168 | if [ -f "$sourceFile" ]; then 169 | replaceAllOccurrences $sourceFile "GoDaddy Email Marketing" "Mad Mimi Sign Up Forms" "$ALLOWED_FILES_MASK$" $saveChanges 170 | replaceAllOccurrences $sourceFile "gem" "mimi" "$ALLOWED_FILES_MASK$" $saveChanges 171 | replaceAllOccurrences $sourceFile "GEM" "Mad_Mimi" "$ALLOWED_FILES_MASK$" $saveChanges 172 | replaceAllOccurrences $sourceFile "wp-godaddy-email-marketing" "madmimi-wp" "$ALLOWED_FILES_MASK$" $saveChanges 173 | replaceAllOccurrences $sourceFile "godaddy" "madmimi" "$ALLOWED_FILES_MASK$" $saveChanges 174 | replaceAllOccurrences $sourceFile "GoDaddy" "Mad Mimi" "$ALLOWED_FILES_MASK$" $saveChanges 175 | 176 | renameFile $sourceFile "gem" "mimi" $saveChanges 177 | renameFile $sourceFile "godaddy" "madmimi" $saveChanges 178 | fi 179 | done 180 | 181 | echo "Done" -------------------------------------------------------------------------------- /includes/class-dispatcher.php: -------------------------------------------------------------------------------- 1 | $username, 23 | 'api_key' => $api_key, 24 | ); 25 | 26 | // Prepare the URL that includes our credentials 27 | $response = wp_remote_get( self::get_method_url( 'forms', false, $auth ), array( 28 | 'timeout' => 10, 29 | ) ); 30 | 31 | // delete all existing transients for this user 32 | delete_transient( "mimi-{$username}-lists" ); 33 | 34 | // credentials are incorrect 35 | if ( ! in_array( wp_remote_retrieve_response_code( $response ), self::$ok_codes, true ) ) { 36 | 37 | return false; 38 | 39 | } 40 | 41 | $data = json_decode( wp_remote_retrieve_body( $response ) ); 42 | 43 | // @todo should we cache for *always* since we have a button to clear the cache? 44 | // maybe having an expiration on such a thing can bloat wp_options? 45 | set_transient( "mimi-{$username}-lists", $data, defined( DAY_IN_SECONDS ) ? DAY_IN_SECONDS : 60 * 60 * 24 ); 46 | 47 | return $data; 48 | 49 | } 50 | 51 | public static function get_forms( $username = false ) { 52 | 53 | $username = $username ? $username : Mad_Mimi_Settings_Controls::get_option( 'username' ); 54 | $api_key = Mad_Mimi_Settings_Controls::get_option( 'api-key' ); 55 | 56 | if ( empty( $api_key ) ) { 57 | 58 | return false; 59 | 60 | } 61 | 62 | $data = get_transient( "mimi-{$username}-lists" ); 63 | 64 | if ( false === $data ) { 65 | 66 | $data = self::fetch_forms( $username ); 67 | 68 | } 69 | 70 | return $data; 71 | 72 | } 73 | 74 | public static function get_fields( $form_id ) { 75 | 76 | $fields = get_transient( "mimi-form-{$form_id}" ); 77 | 78 | if ( false === $fields ) { 79 | 80 | // fields are not cached. fetch and cache. 81 | $fields = wp_remote_get( self::get_method_url( 'fields', array( 82 | 'id' => $form_id, 83 | ) ) ); 84 | 85 | // was there an error, connection is down? bail and try again later. 86 | if ( ! self::is_response_ok( $fields ) ) { 87 | 88 | return false; 89 | 90 | } 91 | 92 | $fields = json_decode( wp_remote_retrieve_body( $fields ) ); 93 | 94 | // @TODO: should we cache results for longer than a day? not expire at all? 95 | set_transient( "mimi-form-{$form_id}", $fields ); 96 | 97 | } 98 | 99 | return $fields; 100 | 101 | } 102 | 103 | public static function get_user_level() { 104 | 105 | $username = Mad_Mimi_Settings_Controls::get_option( 'username' ); 106 | 107 | // no username entered by user? 108 | if ( ! $username ) { 109 | 110 | return false; 111 | 112 | } 113 | 114 | $data = get_transient( "mimi-{$username}-account" ); 115 | 116 | if ( false === $data ) { 117 | 118 | $data = wp_remote_get( self::get_method_url( 'account' ) ); 119 | 120 | // if the request has failed for whatever reason 121 | if ( ! self::is_response_ok( $data ) ) { 122 | 123 | return false; 124 | 125 | } 126 | 127 | $data = json_decode( wp_remote_retrieve_body( $data ) ); 128 | $data = $data->result; 129 | 130 | // no need to expire at all 131 | set_transient( "mimi-{$username}-account", $data ); 132 | 133 | } 134 | 135 | return $data; 136 | 137 | } 138 | 139 | public static function user_sign_in() { 140 | 141 | // Prepare the URL that includes our credentials 142 | $response = wp_remote_get( self::get_method_url( 'signin', false ), array( 143 | 'timeout' => 10, 144 | ) ); 145 | 146 | // credentials are incorrect 147 | if ( ! in_array( wp_remote_retrieve_response_code( $response ), self::$ok_codes, true ) ) { 148 | 149 | return false; 150 | 151 | } 152 | 153 | // retrieve the token 154 | return self::get_method_url( 'signin_redirect', array( 155 | 'token' => wp_remote_retrieve_body( $response ), 156 | ) ); 157 | 158 | } 159 | 160 | /** 161 | * Utility function for getting a URL for various API methods 162 | * 163 | * @param string $method The short of the API method 164 | * @param array $params Extra parameters to pass on with the request 165 | * @param bool $auth Autentication array including API key and username 166 | * 167 | * @return string The final URL to use for the request 168 | */ 169 | public static function get_method_url( $method, $params = array(), $auth = false ) { 170 | 171 | $auth = $auth ? $auth : array( 172 | 'username' => Mad_Mimi_Settings_Controls::get_option( 'username' ), 173 | 'api_key' => Mad_Mimi_Settings_Controls::get_option( 'api-key' ), 174 | ); 175 | 176 | $path = ''; 177 | 178 | switch ( $method ) { 179 | 180 | case 'forms' : 181 | 182 | $path = add_query_arg( $auth, 'signups.json' ); 183 | 184 | break; 185 | 186 | case 'fields' : 187 | 188 | $path = add_query_arg( $auth, "signups/{$params['id']}.json" ); 189 | 190 | break; 191 | 192 | case 'account' : 193 | 194 | $path = add_query_arg( $auth, 'user/account_status' ); 195 | 196 | break; 197 | 198 | case 'signin' : 199 | 200 | $path = add_query_arg( $auth, 'sessions/single_signon_token' ); 201 | 202 | break; 203 | 204 | case 'signin_redirect' : 205 | 206 | $path = add_query_arg( array( 207 | 'token' => $params['token'], 208 | 'username' => $auth['username'], 209 | ), 'sessions/single_signon' ); 210 | 211 | break; 212 | } 213 | 214 | return self::BASE_API . $path; 215 | 216 | } 217 | 218 | public static function is_response_ok( &$request ) { 219 | 220 | return ( ! is_wp_error( $request ) && in_array( wp_remote_retrieve_response_code( $request ), self::$ok_codes, true ) ); 221 | 222 | } 223 | 224 | } 225 | -------------------------------------------------------------------------------- /languages/mad-mimi-sign-up-forms.pot: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 GoDaddy Operating Company, LLC. All Rights Reserved. 2 | msgid "" 3 | msgstr "" 4 | "Project-Id-Version: \n" 5 | "Report-Msgid-Bugs-To: https://github.com/madmimi/madmimi-wp/issues\n" 6 | "POT-Creation-Date: 2020-04-09 17:01:54+00:00\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=utf-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "PO-Revision-Date: 2020-MO-DA HO:MI+ZONE\n" 11 | "Last-Translator: FULL NAME \n" 12 | "Language-Team: LANGUAGE \n" 13 | "X-Poedit-KeywordsList: " 14 | "__;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_" 15 | "attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;esc_html_x:1,2c;\n" 16 | "X-Generator: grunt-wp-i18n 1.0.3\n" 17 | 18 | #: includes/render.php:41 19 | msgid "Powered by Mad Mimi" 20 | msgstr "" 21 | 22 | #: includes/render.php:385 23 | msgid "Month" 24 | msgstr "" 25 | 26 | #: includes/render.php:386 27 | msgid "January" 28 | msgstr "" 29 | 30 | #: includes/render.php:387 31 | msgid "Febuary" 32 | msgstr "" 33 | 34 | #: includes/render.php:388 35 | msgid "March" 36 | msgstr "" 37 | 38 | #: includes/render.php:389 39 | msgid "April" 40 | msgstr "" 41 | 42 | #: includes/render.php:390 43 | msgid "May" 44 | msgstr "" 45 | 46 | #: includes/render.php:391 47 | msgid "June" 48 | msgstr "" 49 | 50 | #: includes/render.php:392 51 | msgid "July" 52 | msgstr "" 53 | 54 | #: includes/render.php:393 55 | msgid "August" 56 | msgstr "" 57 | 58 | #: includes/render.php:394 59 | msgid "September" 60 | msgstr "" 61 | 62 | #: includes/render.php:395 63 | msgid "October" 64 | msgstr "" 65 | 66 | #: includes/render.php:396 67 | msgid "November" 68 | msgstr "" 69 | 70 | #: includes/render.php:397 71 | msgid "December" 72 | msgstr "" 73 | 74 | #: includes/render.php:402 75 | msgid "Day" 76 | msgstr "" 77 | 78 | #: includes/render.php:412 79 | msgid "Year" 80 | msgstr "" 81 | 82 | #: includes/settings.php:26 includes/settings.php:27 includes/settings.php:297 83 | msgid "Mad Mimi Settings" 84 | msgstr "" 85 | 86 | #: includes/settings.php:89 87 | msgid "All transients were removed." 88 | msgstr "" 89 | 90 | #: includes/settings.php:104 91 | msgid "Forms list was successfully updated." 92 | msgstr "" 93 | 94 | #: includes/settings.php:171 95 | msgid "Overview" 96 | msgstr "" 97 | 98 | #: includes/settings.php:210 99 | msgid "Mad Mimi Help Docs" 100 | msgstr "" 101 | 102 | #: includes/settings.php:211 103 | msgid "Mad Mimi Blog" 104 | msgstr "" 105 | 106 | #: includes/settings.php:212 107 | msgid "Contact Mad Mimi" 108 | msgstr "" 109 | 110 | #: includes/settings.php:236 111 | msgid "Account Details" 112 | msgstr "" 113 | 114 | #: includes/settings.php:243 115 | msgid "Mad Mimi Username" 116 | msgstr "" 117 | 118 | #: includes/settings.php:250 119 | msgid "Your Mad Mimi username (email address)" 120 | msgstr "" 121 | 122 | #: includes/settings.php:257 123 | msgid "Mad Mimi API Key" 124 | msgstr "" 125 | 126 | #: includes/settings.php:266 127 | msgid "Where can I find my API key?" 128 | msgstr "" 129 | 130 | #: includes/settings.php:283 131 | msgid "Display \"Powered by Mad Mimi\"?" 132 | msgstr "" 133 | 134 | #: includes/settings.php:303 135 | msgid "Enjoy the Mad Mimi Experience, first hand." 136 | msgstr "" 137 | 138 | #: includes/settings.php:305 139 | msgid "" 140 | "Add your Mad Mimi webform to your WordPress site! Easy to set up, the Mad " 141 | "Mimi plugin allows your site visitors to subscribe to your email list." 142 | msgstr "" 143 | 144 | #: includes/settings.php:311 145 | #. translators: 1. Link to the Mad Mimi account signup. 146 | msgid "Don't have a Mad Mimi account? Get one in less than 2 minutes! %s" 147 | msgstr "" 148 | 149 | #: includes/settings.php:314 150 | msgid "Sign Up Now" 151 | msgstr "" 152 | 153 | #: includes/settings.php:332 154 | msgid "Save Settings" 155 | msgstr "" 156 | 157 | #: includes/settings.php:336 158 | msgid "Available Forms" 159 | msgstr "" 160 | 161 | #: includes/settings.php:342 includes/settings.php:350 162 | msgid "Form Name" 163 | msgstr "" 164 | 165 | #: includes/settings.php:343 includes/settings.php:351 166 | msgid "Form ID" 167 | msgstr "" 168 | 169 | #: includes/settings.php:344 includes/settings.php:352 170 | msgid "Shortcode" 171 | msgstr "" 172 | 173 | #: includes/settings.php:380 174 | msgid "Opens in a new window" 175 | msgstr "" 176 | 177 | #: includes/settings.php:380 178 | msgid "Edit form in Mad Mimi" 179 | msgstr "" 180 | 181 | #: includes/settings.php:383 182 | msgid "Preview" 183 | msgstr "" 184 | 185 | #: includes/settings.php:402 186 | msgid "No forms found" 187 | msgstr "" 188 | 189 | #: includes/settings.php:413 190 | msgid "Not seeing your form?" 191 | msgstr "" 192 | 193 | #: includes/settings.php:413 194 | msgid "Refresh Forms" 195 | msgstr "" 196 | 197 | #: includes/settings.php:418 198 | msgid "Debug" 199 | msgstr "" 200 | 201 | #: includes/settings.php:420 202 | msgid "Erase All Data" 203 | msgstr "" 204 | 205 | #: includes/settings.php:421 206 | msgid "Erase Transients" 207 | msgstr "" 208 | 209 | #: includes/settings.php:444 210 | msgid "" 211 | "The credentials are incorrect! Please verify that you have entered them " 212 | "correctly." 213 | msgstr "" 214 | 215 | #: includes/settings.php:451 216 | msgid "Connection with Mad Mimi has been established! You're all set!" 217 | msgstr "" 218 | 219 | #: includes/settings.php:458 220 | msgid "Please fill in the username and the API key first." 221 | msgstr "" 222 | 223 | #: includes/settings.php:474 224 | msgid "" 225 | "Please enter your Mad Mimi username and API Key in order to be able to " 226 | "create forms." 227 | msgstr "" 228 | 229 | #: includes/widget.php:12 includes/widget.php:40 230 | msgid "Mad Mimi Form" 231 | msgstr "" 232 | 233 | #: includes/widget.php:14 234 | msgid "Embed any Mad Mimi webform in your sidebar." 235 | msgstr "" 236 | 237 | #: includes/widget.php:88 238 | msgid "Title:" 239 | msgstr "" 240 | 241 | #: includes/widget.php:93 242 | msgid "Additional Text:" 243 | msgstr "" 244 | 245 | #: includes/widget.php:101 246 | msgid "Form:" 247 | msgstr "" 248 | 249 | #: includes/widget.php:118 250 | #. translators: Link to the settings page. 251 | msgid "Please set up your Mad Mimi account in the %s." 252 | msgstr "" 253 | 254 | #: includes/widget.php:122 255 | msgid "settings page" 256 | msgstr "" -------------------------------------------------------------------------------- /madmimiofficial.php: -------------------------------------------------------------------------------- 1 | setup_constants(); 34 | self::$instance->requirements(); 35 | self::$instance->setup_actions(); 36 | 37 | } 38 | 39 | private function setup_actions() { 40 | 41 | add_action( 'init', array( $this, 'init' ) ); 42 | add_action( 'widgets_init', array( $this, 'register_widget' ) ); 43 | add_action( 'init', array( $this, 'register_shortcode' ), 20 ); 44 | add_action( 'admin_notices', array( $this, 'action_admin_notices' ) ); 45 | 46 | add_filter( 'plugin_action_links_' . self::$basename, array( $this, 'action_links' ), 10 ); 47 | 48 | register_activation_hook( __FILE__, array( $this, 'activate' ) ); 49 | register_deactivation_hook( __FILE__, array( $this, 'deactivate' ) ); 50 | 51 | } 52 | 53 | private function setup_constants() { 54 | 55 | // Plugin's main directory 56 | if ( ! defined( 'MADMIMI_PLUGIN_DIR' ) ) { 57 | 58 | define( 'MADMIMI_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 59 | 60 | } 61 | 62 | // Absolute URL to plugin's dir 63 | if ( ! defined( 'MADMIMI_PLUGIN_URL' ) ) { 64 | 65 | define( 'MADMIMI_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); 66 | 67 | } 68 | 69 | // Absolute URL to plugin's dir 70 | if ( ! defined( 'MADMIMI_PLUGIN_BASE' ) ) { 71 | 72 | define( 'MADMIMI_PLUGIN_BASE', plugin_basename( __FILE__ ) ); 73 | 74 | } 75 | 76 | // Plugin version 77 | if ( ! defined( 'MADMIMI_VERSION' ) ) { 78 | 79 | define( 'MADMIMI_VERSION', '1.5.1' ); 80 | 81 | } 82 | 83 | self::$basename = isset( self::$basename ) ? self::$basename : MADMIMI_PLUGIN_BASE; 84 | 85 | } 86 | 87 | // @todo include only some on is_admin() 88 | private function requirements() { 89 | 90 | require_once MADMIMI_PLUGIN_DIR . 'includes/class-dispatcher.php'; 91 | 92 | // the shortcode 93 | require_once MADMIMI_PLUGIN_DIR . 'includes/class-shortcode.php'; 94 | 95 | // the file renders the form 96 | require_once MADMIMI_PLUGIN_DIR . 'includes/render.php'; 97 | 98 | // the main widget 99 | require_once MADMIMI_PLUGIN_DIR . 'includes/widget.php'; 100 | 101 | // settings page, creds validation 102 | require_once MADMIMI_PLUGIN_DIR . 'includes/settings.php'; 103 | 104 | } 105 | 106 | public function init() { 107 | 108 | // enable debug mode? 109 | $this->debug = (bool) apply_filters( 'madmimi_debug', false ); 110 | 111 | // initialize settings 112 | if ( is_admin() ) { 113 | 114 | $this->settings = new Mad_Mimi_Settings(); 115 | 116 | } 117 | 118 | // enqueue scripts n styles 119 | add_action( 'wp_enqueue_scripts', array( $this, 'enqueue' ) ); 120 | 121 | // Load our textdomain to allow multilingual translations 122 | load_plugin_textdomain( 'mad-mimi-sign-up-forms', false, dirname( self::$basename ) . '/languages/' ); 123 | 124 | } 125 | 126 | public function register_shortcode() { 127 | 128 | // register shortcode 129 | add_shortcode( 'madmimi', array( 'Mad_Mimi_Shortcode', 'render' ) ); 130 | add_shortcode( 'MadMimi', array( 'Mad_Mimi_Shortcode', 'render' ) ); 131 | 132 | } 133 | 134 | public function register_widget() { 135 | 136 | register_widget( 'Mad_Mimi_Form_Widget' ); 137 | 138 | } 139 | 140 | public function enqueue() { 141 | 142 | $suffix = SCRIPT_DEBUG ? '' : '.min'; 143 | $rtl = ! is_rtl() ? '' : '-rtl'; 144 | 145 | // main JavaScript file 146 | wp_enqueue_script( 'mimi-main', plugins_url( "js/mimi{$suffix}.js", __FILE__ ), array( 'jquery' ), MADMIMI_VERSION, true ); 147 | 148 | // assistance CSS 149 | wp_enqueue_style( 'mimi-base', plugins_url( "css/mimi{$suffix}.css", __FILE__ ), false, MADMIMI_VERSION ); 150 | 151 | // help strings 152 | wp_localize_script( 'mimi-main', 'MadMimi', array( 153 | 'thankyou' => __( 'Thank you for signing up!', 'mad-mimi-sign-up-forms' ), 154 | 'thankyou_suppressed' => __( 'Thank you for signing up! Please check your email to confirm your subscription.', 'mad-mimi-sign-up-forms' ), 155 | 'oops' => __( 'Oops! There was a problem. Please try again.', 'mad-mimi-sign-up-forms' ), 156 | 'fix' => __( 'There was a problem. Please fill all required fields.', 'mad-mimi-sign-up-forms' ), 157 | ) ); 158 | 159 | } 160 | 161 | public function action_links( $actions ) { 162 | 163 | return array_merge( 164 | array( 165 | 'settings' => sprintf( '%s', menu_page_url( 'mad-mimi-settings', false ), __( 'Settings', 'mad-mimi-sign-up-forms' ) ), 166 | ), 167 | $actions 168 | ); 169 | 170 | } 171 | 172 | public function activate() { 173 | // nothing to do here (for now) 174 | } 175 | 176 | public function deactivate() { 177 | 178 | delete_option( 'madmimi-version' ); 179 | 180 | } 181 | 182 | public function action_admin_notices() { 183 | 184 | $screen = get_current_screen(); 185 | 186 | if ( 'plugins' !== $screen->id ) { 187 | 188 | return; 189 | 190 | } 191 | 192 | $version = get_option( 'madmimi-version' ); 193 | 194 | if ( ! $version ) { 195 | 196 | update_option( 'madmimi-version', MADMIMI_VERSION ); ?> 197 | 198 |
199 |

200 |   201 | 202 |

203 |
204 | 205 | = 5.4](https://img.shields.io/badge/php-%3E=%205.4-8892bf.svg)](https://secure.php.net/supported-versions.php) [![WordPress >= 4.4](https://img.shields.io/badge/wordpress-%3E=%204.4-blue.svg)](https://wordpress.org/download/release-archive/) 15 | 16 | ## Description ## 17 | 18 | The Official Mad Mimi Signup Form plugin makes it easy to grow your subscribers! Use this plugin to integrate your sign up forms into your WordPress site. 19 | 20 | Once the plugin is activated, you can select and insert any of your Mad Mimi webforms right into your site by using a widget, shortcode, or template tag. Setup is easy; in Settings, simply enter your account email address and API key (found in your [Mad Mimi account](http://help.madmimi.com/where-can-i-find-my-api-key/) area), and you're all set. 21 | 22 | Official Mad Mimi Forms plugin features: 23 | 24 | * Automatically add new forms for users to sign up to an email list of your choice 25 | * Insert unlimited signup forms using the widget, shortcode, or template tag 26 | * Use quick links to edit and preview your form in Mad Mimi 27 | 28 | ## Installation ## 29 | 30 | 1. [Install the plugin manually](https://codex.wordpress.org/Managing_Plugins#Manual_Plugin_Installation) by uploading a ZIP file, or [install it automatically](https://codex.wordpress.org/Managing_Plugins#Automatic_Plugin_Installation) by searching for **Mad Mimi Signup Forms**. 31 | 2. Once the plugin has been installed, click **Activate**. 32 | 3. Nagivate to **Settings > Mad Mimi Settings**. 33 | 4. Enter your Mad Mimi username and API key. 34 | 5. Click **Save Settings**. 35 | 36 | After your account is verified, you can insert a form into your site by using a **widget**, **shortcode**, or **template tag** directly in your theme. See the FAQ section for more details. 37 | 38 | ## Frequently Asked Questions ## 39 | 40 | ### What is Mad Mimi? ### 41 | 42 | [Mad Mimi](https://madmimi.com) is the easiest way to create, send, share, and track email newsletters online. It's for people who want email marketing to be simple. 43 | 44 | ### Do I need a Mad Mimi account to use this plugin? ### 45 | 46 | Yes, this plugin requires a [Mad Mimi](https://madmimi.com) account. 47 | 48 | ### Is there a widget? ### 49 | 50 | Absolutely. Use it by finding the Mad Mimi Form widget under **Appearance > Widgets** in the WordPress Dashboard and dragging it into the widget area of your choice. You can then add a title and select a form! 51 | 52 | ### Is there a shortcode? ### 53 | 54 | Yes! You can add a form to any post or page by adding the shortcode with the form ID (e.g., `[madmimi id=123456 ]`) in the page/post editor. 55 | 56 | ### Is there a template tag? ### 57 | 58 | Yup! Add the following template tag into any WordPress theme template file: ``. For example: `` where `123456` is your form ID. 59 | 60 | ### Where can I find my form IDs? ### 61 | 62 | To find your form IDs, navigate to **Settings > Mad Mimi Settings** and scroll down to the **Available Forms** section. If you've recently created new forms click the **Refresh Forms** button to pull them into your WordPress site. 63 | 64 | ### Where can I find the API Key? ### 65 | 66 | Your API Key can be found in your Mad Mimi account area. For more details [see this help article](https://help.madmimi.com/where-can-i-find-my-api-key/). 67 | 68 | ## Screenshots ## 69 | 70 | 1. Settings screen. 71 | 2. A full list of your Mad Mimi forms, with handy shortcodes. 72 | 3. The widget on the front-end. 73 | 4. The widget on the widgets page. 74 | 75 | ## Changelog ## 76 | 77 | ### 1.7.1 ### 78 | * Fix: Resolve PHP notice. 79 | * Tweak: Test with and bump support for WordPress 5.4. 80 | 81 | ### 1.7.0 ### 82 | * New: Add support for GDPR fields (Age consent, terms of service and tracking option) 83 | 84 | ### 1.6.0 ### 85 | * New: Reference to jQuery UI has been removed. 86 | * Tweak: Styles updated for MadMimi fancy fields. 87 | * Fix: Resolved 'Mixed Content' warning when using on sites with SSL enabled. 88 | * Fix: Various code improvements. 89 | 90 | ### 1.5.1 ### 91 | * Fixed shortcode display. 92 | 93 | ### 1.5 ### 94 | * This update includes various bug fixes. 95 | 96 | ### 1.4 ### 97 | * Added support for web form fancy fields 98 | * Made some styling changes to mobile view 99 | 100 | ### 1.3 ### 101 | * Coding standards 102 | * Fixed up some improper escaping and sanitization 103 | * Updated Admin UI to more closely match default WordPress style 104 | * Minor improvements to plugin copy 105 | 106 | ### 1.2 ### 107 | * Fixed the padding for p tags in the mad mimi signup form 108 | 109 | ### 1.1 ### 110 | * New! Upon form submit, the plugin checks to see if the Mad Mimi user has specified that the new subscriber should be redirected to a specific webpage after subscribing (Confirmation Landing Page). If the user has specified a Confirmation Landing Page for their webform, the new subscriber will be redirected to that page after subscribing. 111 | * Better cache handling for the provided CSS and JS core files 112 | * Bug fixes 113 | 114 | ### 1.0 ### 115 | * Initial version. Hoozah! 116 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | /* global module, require */ 2 | 3 | module.exports = function( grunt ) { 4 | 5 | 'use strict'; 6 | 7 | var pkg = grunt.file.readJSON( 'package.json' ); 8 | 9 | grunt.initConfig( { 10 | 11 | pkg: pkg, 12 | 13 | clean: { 14 | build: [ 'build/' ] 15 | }, 16 | 17 | copy: { 18 | build: { 19 | files: [ 20 | { 21 | expand: true, 22 | src: [ 23 | '*.php', 24 | 'css/**', 25 | 'images/**', 26 | 'includes/**', 27 | 'js/**', 28 | 'languages/*.{mo,pot}', 29 | 'license.txt', 30 | 'readme.txt', 31 | '!**/*.{ai,eps,psd}' 32 | ], 33 | dest: 'build/' 34 | } 35 | ] 36 | } 37 | }, 38 | 39 | cssjanus: { 40 | theme: { 41 | options: { 42 | swapLtrRtlInUrl: false 43 | }, 44 | files: [ 45 | { 46 | expand: true, 47 | cwd: 'css/', 48 | src: [ '*.css', '!*-rtl.css', '!*.min.css', '!*-rtl.min.css' ], 49 | dest: 'css/', 50 | ext: '-rtl.css' 51 | } 52 | ] 53 | } 54 | }, 55 | 56 | cssmin: { 57 | options: { 58 | processImport: false, 59 | roundingPrecision: -1, 60 | shorthandCompacting: false 61 | }, 62 | all: { 63 | files: [ 64 | { 65 | expand: true, 66 | cwd: 'css/', 67 | src: [ '**/*.css', '!**/*.min.css' ], 68 | dest: 'css/', 69 | ext: '.min.css' 70 | } 71 | ] 72 | } 73 | }, 74 | 75 | imagemin: { 76 | options: { 77 | optimizationLevel: 3 78 | }, 79 | assets: { 80 | expand: true, 81 | cwd: 'images/', 82 | src: [ '**/*.{gif,jpeg,jpg,png,svg}' ], 83 | dest: 'images/' 84 | }, 85 | wp_org_assets: { 86 | expand: true, 87 | cwd: 'wp-org-assets/', 88 | src: [ '**/*.{gif,jpeg,jpg,png,svg}' ], 89 | dest: 'wp-org-assets/' 90 | } 91 | }, 92 | 93 | jshint: { 94 | assets: [ 'js/**/*.js', '!js/**/*.min.js', '!js/jquery-ui.*' ], 95 | gruntfile: [ 'Gruntfile.js' ] 96 | }, 97 | 98 | makepot: { 99 | target: { 100 | options: { 101 | domainPath: 'languages/', 102 | include: [ pkg.name + '.php', 'includes/.+\.php' ], 103 | mainFile: pkg.name + '.php', 104 | potComments: 'Copyright (c) {year} GoDaddy Operating Company, LLC. All Rights Reserved.', 105 | potFilename: pkg.name + '.pot', 106 | potHeaders: { 107 | 'x-poedit-keywordslist': true 108 | }, 109 | processPot: function( pot, options ) { 110 | pot.headers['report-msgid-bugs-to'] = pkg.bugs.url; 111 | return pot; 112 | }, 113 | type: 'wp-plugin', 114 | updatePoFiles: true 115 | } 116 | } 117 | }, 118 | 119 | replace: { 120 | php: { 121 | src: [ 122 | 'madmimiofficial.php', 123 | 'includes/**/*.php' 124 | ], 125 | overwrite: true, 126 | replacements: [ 127 | { 128 | from: /Version:(\s*?)[a-zA-Z0-9\.\-\+]+$/m, 129 | to: 'Version:$1' + pkg.version 130 | }, 131 | { 132 | from: /@since(.*?)NEXT/mg, 133 | to: '@since$1' + pkg.version 134 | }, 135 | { 136 | from: /@deprecated(\s+)NEXT/g, 137 | to: '@deprecated$1<%= pkg.version %>' 138 | }, 139 | { 140 | from: /@NEXT/g, 141 | to: '<%= pkg.version %>' 142 | }, 143 | { 144 | from: /VERSION(\s*?)=(\s*?['"])[a-zA-Z0-9\.\-\+]+/mg, 145 | to: 'VERSION$1=$2' + pkg.version 146 | } 147 | ] 148 | }, 149 | readme: { 150 | src: 'readme.*', 151 | overwrite: true, 152 | replacements: [ 153 | { 154 | from: /^(\*\*|)Stable tag:(\*\*|)(\s*?)[a-zA-Z0-9.-]+(\s*?)$/mi, 155 | to: '$1Stable tag:$2$3<%= pkg.version %>$4' 156 | }, 157 | { 158 | from: /@NEXT/g, 159 | to: '<%= pkg.version %>' 160 | } 161 | ] 162 | } 163 | }, 164 | 165 | uglify: { 166 | options: { 167 | ASCIIOnly: true 168 | }, 169 | all: { 170 | expand: true, 171 | cwd: 'js/', 172 | src: [ '**/*.js', '!**/*.min.js' ], 173 | dest: 'js/', 174 | ext: '.min.js' 175 | } 176 | }, 177 | 178 | watch: { 179 | css: { 180 | files: [ 'css/**/*.css', '!css/**/*.min.css' ], 181 | tasks: [ 'cssjanus', 'cssmin' ] 182 | }, 183 | images: { 184 | files: [ 185 | 'images/**/*.{gif,jpeg,jpg,png,svg}', 186 | 'wp-org-assets/**/*.{gif,jpeg,jpg,png,svg}' 187 | ], 188 | tasks: [ 'imagemin' ] 189 | }, 190 | js: { 191 | files: [ 'js/**/*.js', '!js/**/*.min.js' ], 192 | tasks: [ 'jshint', 'uglify' ] 193 | }, 194 | readme: { 195 | files: 'readme.txt', 196 | tasks: [ 'readme' ] 197 | } 198 | }, 199 | 200 | wp_deploy: { 201 | plugin: { 202 | options: { 203 | assets_dir: 'wp-org-assets/', 204 | build_dir: 'build/', 205 | plugin_main_file: 'madmimiofficial.php', 206 | plugin_slug: pkg.name 207 | } 208 | } 209 | }, 210 | 211 | wp_readme_to_markdown: { 212 | options: { 213 | post_convert: function( readme ) { 214 | var matches = readme.match( /\*\*Tags:\*\*(.*)\r?\n/ ), 215 | tags = matches[1].trim().split( ', ' ), 216 | section = matches[0]; 217 | 218 | for ( var i = 0; i < tags.length; i++ ) { 219 | 220 | section = section.replace( tags[i], '[' + tags[i] + '](https://wordpress.org/plugins/tags/' + tags[i].replace( ' ', '-' ) + '/)' ); 221 | 222 | } 223 | 224 | // Banner 225 | if ( grunt.file.exists( 'wp-org-assets/banner-1544x500.png' ) ) { 226 | readme = readme.replace( '**Contributors:**', "![Banner Image](wp-org-assets/banner-1544x500.png)\r\n\r\n**Contributors:**" ); 227 | } 228 | 229 | // Tag links 230 | readme = readme.replace( matches[0], section ); 231 | 232 | // Badges 233 | readme = readme.replace( '## Description ##', grunt.template.process( pkg.badges.join( ' ' ) ) + " \r\n\r\n## Description ##" ); 234 | 235 | // YouTube 236 | readme = readme.replace( /\[youtube\s+(?:https?:\/\/www\.youtube\.com\/watch\?v=|https?:\/\/youtu\.be\/)(.+?)\]/g, '[![Play video on YouTube](https://img.youtube.com/vi/$1/maxresdefault.jpg)](https://www.youtube.com/watch?v=$1)' ); 237 | 238 | return readme; 239 | } 240 | }, 241 | main: { 242 | files: { 243 | 'readme.md': 'readme.txt' 244 | } 245 | } 246 | } 247 | 248 | } ); 249 | 250 | require( 'matchdep' ).filterDev( 'grunt-*' ).forEach( grunt.loadNpmTasks ); 251 | 252 | grunt.registerTask( 'default', [ 'cssjanus', 'cssmin', 'jshint', 'uglify', 'imagemin', 'readme' ] ); 253 | grunt.registerTask( 'build', [ 'default', 'clean:build', 'copy:build' ] ); 254 | grunt.registerTask( 'deploy', [ 'build', 'wp_deploy', 'clean:build' ] ); 255 | grunt.registerTask( 'readme', [ 'wp_readme_to_markdown' ] ); 256 | grunt.registerTask( 'update-pot', [ 'makepot' ] ); 257 | grunt.registerTask( 'version', [ 'replace', 'readme' ] ); 258 | 259 | }; 260 | -------------------------------------------------------------------------------- /js/mimi.js: -------------------------------------------------------------------------------- 1 | ;( function( $, undefined ) { 2 | 3 | "use strict"; 4 | 5 | var MadMimi = window.MadMimi || {}; 6 | 7 | /** 8 | * Constants 9 | */ 10 | MadMimi.DEBUG_FLAG = true; 11 | 12 | MadMimi.init = function() { 13 | 14 | // Handles form submissions 15 | $( 'form.mimi-form' ).submit( function( e ) { 16 | 17 | e.preventDefault(); 18 | 19 | //code that handles multiple selected checkboxes and saves them as comma separated (value1, value2) 20 | //which needed to happen before the payload gets serialized 21 | var combined_checkbox_string = '', 22 | check_box_test = 0, 23 | current_name_of_input = ''; 24 | $( this ).find( ':input' ).each( function( i ) { 25 | var name_of_input = $(this).attr('name'); 26 | 27 | if($(this).attr('type') == 'checkbox' && $(this).is(':checked')){ 28 | 29 | if(current_name_of_input != name_of_input) 30 | { 31 | current_name_of_input = name_of_input; 32 | check_box_test = 0; 33 | } 34 | 35 | if(check_box_test == 0) 36 | { 37 | combined_checkbox_string = $("input:checkbox[name='"+name_of_input+"']:checked").map(function() {return this.value;}).get().join(', '); 38 | check_box_test = 1; 39 | } 40 | 41 | $("input[name='"+name_of_input+"']").val(combined_checkbox_string); 42 | 43 | } 44 | }); 45 | //end of multiple checkbox select code 46 | 47 | //code that handles multiple selected dropdowns for the date and saves them as MM dd, yy (Oct 29, 15) 48 | //which needed to happen before the payload gets serialized 49 | var combined_date_string = '', 50 | date_test = 0, 51 | current_name_of_date = ''; 52 | 53 | var values = []; 54 | 55 | $( this ).find("[fingerprint='date']" ).each( function( i ) { 56 | var name_of_input = $(this).attr('name'); 57 | 58 | 59 | if($(this).attr('fingerprint') == 'date'){ 60 | 61 | if(current_name_of_date != name_of_input) 62 | { 63 | current_name_of_date = name_of_input; 64 | values=[]; 65 | combined_date_string=''; 66 | } 67 | 68 | values.push($(this).val()); 69 | 70 | if(values.length == 3) 71 | { 72 | //building the value with correct formatting... MM dd, yy (Oct 29, 15) 73 | combined_date_string = values[0] + ' ' + values[1] + ', ' + values[2]; 74 | } 75 | 76 | $("input[name='"+name_of_input+"']").val(combined_date_string); 77 | } 78 | }); 79 | //end of multiple date dropdown select code 80 | 81 | var $wrapper = $( this ), 82 | $spinner = $( '.mimi-spinner', $wrapper ), 83 | 84 | /* needed only when using WP as a proxy. 85 | payload = $.extend( {}, $( this ).mimiSerializeObject(), { 86 | action: 'mimi-submit-form' 87 | } ), 88 | */ 89 | 90 | payload = $( this ).serialize(), 91 | invalidElements = [], 92 | m = MadMimi; 93 | 94 | //console.log(payload); 95 | 96 | // make sure to clear all "invalid" elements before re-validating 97 | $wrapper.find( 'input.mimi-invalid' ).removeClass( 'mimi-invalid' ); 98 | 99 | //$('.checkbox:checked').map(function() {return this.value;}).get().join(','); 100 | 101 | $( this ).find( ':input' ).each( function( i ) { 102 | 103 | if ( 'signup[email]' == $( this ).attr( 'name' ) && ! MadMimi.isEmail( $( this ).val() ) ) { 104 | 105 | // email not valid 106 | invalidElements.push( $( this ) ); 107 | m.log( 'Email is NOT valid' ); 108 | 109 | } else if ( $( this ).is( 'input[type="checkbox"]' ) && $( this ).hasClass( 'mimi-required' ) && ! $( this ).is( ':checked' ) ) { 110 | 111 | // Empty checkbox. 112 | invalidElements.push( $( this ) ); 113 | m.log( 'A required filled was not filled' ); 114 | 115 | } else if ( $( this ).is( '.mimi-required' ) && '' == $( this ).val() ) { 116 | 117 | invalidElements.push( $( this ) ); 118 | m.log( 'A required filled was not filled' ); 119 | 120 | } 121 | 122 | } ); 123 | 124 | // if there are no empty or invalid fields left... 125 | if ( 0 == invalidElements.length ) { 126 | 127 | // we're good to go! start spinnin' 128 | $spinner.css( 'display', 'inline-block' ); 129 | 130 | $.post( $wrapper.attr( 'action' ) + '.json', payload, function( response ) { 131 | 132 | $wrapper.fadeOut( 'fast', function() { 133 | 134 | // was the user successfully added? 135 | if ( response.success ) { 136 | 137 | var d = response.result, 138 | is_suppressed = d.audience_member.suppressed; 139 | 140 | if ( d.has_redirect ) { 141 | window.location.href = d.redirect; 142 | } 143 | 144 | $wrapper.html( MadMimi.addMessage( 145 | is_suppressed ? [ 'suppressed', 'success' ] : [ 'info', 'success' ], 146 | is_suppressed ? MadMimi.thankyou_suppressed : MadMimi.thankyou ) 147 | ).fadeIn( 'fast' ); 148 | 149 | } else { 150 | $wrapper.html( MadMimi.addMessage( 'info', MadMimi.oops ) ).fadeIn( 'fast' ); 151 | } 152 | 153 | } ); 154 | 155 | }, 'jsonp' ); 156 | 157 | } else { 158 | 159 | // there are invalid elements 160 | $( invalidElements ).each( function( i, el ) { 161 | $( this ).addClass( 'mimi-invalid' ); 162 | } ); 163 | 164 | var previousNotifications = $wrapper.find( '.mimi-error, .mimi-info' ); 165 | 166 | if ( 0 != previousNotifications.length ) { 167 | previousNotifications.remove(); 168 | } 169 | 170 | $wrapper.prepend( MadMimi.addMessage( 'error', MadMimi.fix ) ); 171 | 172 | } 173 | 174 | } ); 175 | }; 176 | 177 | MadMimi.addMessage = function( type, message ) { 178 | 179 | var _class = []; 180 | 181 | if ( $.isArray( type ) ) { 182 | 183 | $.each( type, function( index, value ) { 184 | _class.push( 'mimi-' + value ); 185 | } ); 186 | 187 | } else { 188 | _class.push( 'mimi-' + type.toString() ); 189 | } 190 | 191 | return $( '

', { class: _class.join( ' ' ) } ).text( message ); 192 | 193 | }; 194 | 195 | MadMimi.isEmail = function ( email ) { 196 | var regex = /^([a-zA-Z0-9_\.\-\+])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/; 197 | return regex.test( email ); 198 | }; 199 | 200 | MadMimi.log = function( message ) { 201 | 202 | if ( MadMimi.DEBUG_FLAG && window.console ) { 203 | console.log( message ); 204 | } 205 | 206 | }; 207 | 208 | /** 209 | * ==== Helpers + Utilities ==== 210 | */ 211 | $.fn.mimiSerializeObject = function() { 212 | 213 | var o = {}; 214 | var a = this.serializeArray(); 215 | 216 | $.each( a, function() { 217 | 218 | if ( o[ this.name ] ) { 219 | 220 | if ( ! o[ this.name ].push ) { 221 | o[ this.name ] = [ o[ this.name ] ]; 222 | } 223 | 224 | o[ this.name ].push( this.value || '' ); 225 | 226 | } else { 227 | o[ this.name ] = this.value || ''; 228 | } 229 | } ); 230 | 231 | return o; 232 | 233 | }; 234 | 235 | /** 236 | * Constructor 237 | */ 238 | $( document ).ready( MadMimi.init ); 239 | 240 | } )( jQuery ); 241 | -------------------------------------------------------------------------------- /includes/render.php: -------------------------------------------------------------------------------- 1 | fields ) ) : 12 | 13 | self::$loops++; 14 | 15 | ob_start(); 16 | 17 | ?> 18 | 19 |

20 |
21 | 22 | fields ); ?> 23 | 24 | fields as $count => $field ) : ?> 25 | 26 |

27 | 28 | 29 | 30 | fields ); ?> 31 | 32 | 39 | 40 |

41 | 42 |

43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 |
52 |
53 | 54 | type ) ) { 79 | 80 | return; 81 | 82 | } 83 | 84 | self::$cycle = absint( $cycle ); 85 | 86 | if ( ! is_null( $field->field_type ) ) { 87 | 88 | $field = self::adjust_field_type( $field ); 89 | 90 | if ( ! method_exists( __CLASS__, $field->field_type ) ) { 91 | 92 | return; 93 | 94 | } 95 | 96 | call_user_func( array( __CLASS__, $field->field_type ), $field ); 97 | 98 | } else { 99 | 100 | call_user_func( array( __CLASS__, $field->type ), $field ); 101 | 102 | } 103 | 104 | } 105 | 106 | public static function get_form_id( $field_name ) { 107 | 108 | // since HTML ID's can't exist in the same exact spelling more than once... make it special. 109 | return sprintf( 'form_%s_%s', self::$cycle, $field_name ); 110 | 111 | } 112 | 113 | public static function string( $args ) { 114 | 115 | $field_classes = array( 'mimi-field' ); 116 | 117 | // is this field required? 118 | if ( $args->required ) { 119 | 120 | $field_classes[] = 'mimi-required'; 121 | 122 | } 123 | 124 | $field_classes = (array) apply_filters( 'mimi_required_field_class', $field_classes, $args ); 125 | 126 | ?> 127 | 128 | 139 | 140 | 141 | 142 | required ) { 153 | 154 | $field_classes[] = 'mimi-required'; 155 | 156 | } 157 | 158 | $field_classes = (array) apply_filters( 'mimi_required_field_class', $field_classes, $args ); 159 | 160 | ?> 161 | 162 | 175 | 176 | required ) { 185 | 186 | $field_classes[] = 'mimi-required'; 187 | 188 | } 189 | 190 | $field_classes = (array) apply_filters( 'mimi_required_field_class', $field_classes, $args ); 191 | 192 | ?> 193 | 194 | 205 | 206 |
207 | 208 | options; 212 | 213 | foreach ( $trim_values as $trim ) { 214 | 215 | $options = trim( $options, $trim ); 216 | 217 | } 218 | 219 | $trimmed_options = array(); 220 | $options = str_replace( '"', '', $options ); 221 | $trimmed_options = explode( ',', $options ); 222 | 223 | foreach ( $trimmed_options as $key => $value ) { 224 | 225 | ?> 226 | 227 |
228 | 229 | 230 | 231 | required ) { 241 | 242 | $field_classes[] = 'mimi-required'; 243 | 244 | } 245 | 246 | $field_classes = (array) apply_filters( 'mimi_required_field_class', $field_classes, $args ); 247 | 248 | ?> 249 | 250 | 261 | 262 |
263 | 264 | 295 | 296 | required ) { 305 | 306 | $field_classes[] = 'mimi-required'; 307 | 308 | } 309 | 310 | $field_classes = (array) apply_filters( 'mimi_required_field_class', $field_classes, $args ); 311 | 312 | ?> 313 | 314 | 325 | 326 |
327 | 328 | options; 332 | 333 | foreach ( $trim_values as $trim ) { 334 | 335 | $options = trim( $options, $trim ); 336 | 337 | } 338 | 339 | $trimmed_options = array(); 340 | $options = str_replace( '"', '', $options ); 341 | $trimmed_options = explode( ',', $options ); 342 | 343 | foreach ( $trimmed_options as $radio_options ) { 344 | 345 | ?> 346 | 347 |
348 | 349 | required ) { 360 | 361 | $field_classes[] = 'mimi-required'; 362 | 363 | } 364 | 365 | $field_classes = (array) apply_filters( 'mimi_required_field_class', $field_classes, $args ); 366 | 367 | ?> 368 | 369 | 380 | 381 | 382 | 383 | 384 | 399 | 400 | 401 | 409 | 410 | 411 | 419 | 420 | 421 | 422 | 423 | required ) { 433 | 434 | $field_classes[] = 'mimi-required'; 435 | 436 | } 437 | 438 | $field_classes = (array) apply_filters( 'mimi_required_field_class', $field_classes, $args ); 439 | 440 | ?> 441 | 442 | 453 | 454 | 455 | 456 | required ) { 471 | $field_classes[] = 'mimi-required'; 472 | } 473 | 474 | $field_classes = (array) apply_filters( 'mimi_required_field_class', $field_classes, $args ); 475 | $field_options = ! empty( $args->options ) ? json_decode( $args->options ) : false; 476 | $tos_link = isset( $field_options->link ) ? $field_options->link : false; 477 | ?> 478 | 479 | 484 | 485 | field_type, [ 'tracking_option', 'age_check' ], true ) ) { 497 | 498 | $field->value = $field->display; 499 | $field->field_type = 'checkbox'; 500 | 501 | } 502 | 503 | return $field; 504 | 505 | } 506 | } 507 | -------------------------------------------------------------------------------- /includes/settings.php: -------------------------------------------------------------------------------- 1 | mimi = madmimi(); // main Mad Mimi instance 12 | 13 | add_action( 'admin_menu', array( $this, 'action_admin_menu' ) ); 14 | add_action( 'admin_init', array( $this, 'register_settings' ) ); 15 | 16 | } 17 | 18 | /** 19 | * Register the settings page 20 | * 21 | * @since 1.0 22 | */ 23 | public function action_admin_menu() { 24 | 25 | $this->hook = add_options_page( // @codingStandardsIgnoreLine 26 | __( 'Mad Mimi Settings', 'mad-mimi-sign-up-forms' ), // tag 27 | __( 'Mad Mimi Settings', 'mad-mimi-sign-up-forms' ), // menu label 28 | 'manage_options', // required cap to view this page 29 | $this->slug = 'mad-mimi-settings', // page slug 30 | array( &$this, 'display_settings_page' ) // callback 31 | ); 32 | 33 | add_action( "load-{$this->hook}", array( $this, 'page_load' ) ); 34 | 35 | } 36 | 37 | public function page_load() { 38 | 39 | // main switch for some various maintenance processes 40 | if ( isset( $_GET['action'] ) ) { // @codingStandardsIgnoreLine 41 | 42 | $settings = get_option( $this->slug ); 43 | 44 | switch ( $_GET['action'] ) { // @codingStandardsIgnoreLine 45 | 46 | case 'debug-reset' : 47 | 48 | if ( ! $this->mimi->debug ) { 49 | 50 | return; 51 | 52 | } 53 | 54 | if ( isset( $settings['username'] ) ) { 55 | 56 | delete_transient( 'mimi-' . $settings['username'] . '-lists' ); 57 | 58 | } 59 | 60 | delete_option( $this->slug ); 61 | 62 | break; 63 | 64 | case 'debug-reset-transients' : 65 | 66 | if ( ! $this->mimi->debug ) { 67 | 68 | return; 69 | 70 | } 71 | 72 | if ( isset( $settings['username'] ) ) { 73 | 74 | // remove all lists 75 | delete_transient( 'mimi-' . $settings['username'] . '-lists' ); 76 | 77 | // mass-removal of all forms 78 | 79 | $forms = Mad_Mimi_Dispatcher::get_forms(); 80 | 81 | if ( $forms && ! empty( $forms->signups ) ) { 82 | 83 | foreach ( $forms->signups as $form ) { 84 | 85 | delete_transient( 'mimi-form-' . $form->id ); 86 | 87 | } 88 | 89 | add_settings_error( $this->slug, 'mimi-reset', __( 'All transients were removed.', 'mad-mimi-sign-up-forms' ), 'updated' ); 90 | 91 | } 92 | } 93 | 94 | 95 | break; 96 | 97 | case 'refresh' : 98 | 99 | // remove only the lists for the current user 100 | if ( isset( $settings['username'] ) ) { 101 | 102 | if ( delete_transient( 'mimi-' . $settings['username'] . '-lists' ) ) { 103 | 104 | add_settings_error( $this->slug, 'mimi-reset', __( 'Forms list was successfully updated.', 'mad-mimi-sign-up-forms' ), 'updated' ); 105 | 106 | } 107 | } 108 | 109 | $forms = Mad_Mimi_Dispatcher::get_forms(); 110 | 111 | if ( $forms && ! empty( $forms->signups ) ) { 112 | 113 | foreach ( $forms->signups as $form ) { 114 | 115 | delete_transient( "mimi-form-{$form->id}" ); 116 | 117 | } 118 | } 119 | 120 | break; 121 | 122 | case 'edit_form' : 123 | 124 | if ( ! isset( $_GET['form_id'] ) ) { // @codingStandardsIgnoreLine 125 | 126 | return; 127 | 128 | } 129 | 130 | $tokenized_url = add_query_arg( 'redirect', sprintf( '/signups/%d/edit', absint( $_GET['form_id'] ) ), Mad_Mimi_Dispatcher::user_sign_in() ); // @codingStandardsIgnoreLine 131 | 132 | // Not wp_safe_redirect as it's an external site 133 | wp_redirect( $tokenized_url ); 134 | 135 | break; 136 | 137 | case 'dismiss' : 138 | 139 | $user_id = get_current_user_id(); 140 | 141 | if ( ! $user_id ) { 142 | 143 | return; 144 | 145 | } 146 | 147 | update_user_meta( $user_id, 'madmimi-dismiss', 'show' ); 148 | 149 | break; 150 | 151 | } // End switch(). 152 | 153 | } // End if(). 154 | 155 | // set up the help tabs 156 | add_action( 'in_admin_header', array( $this, 'setup_help_tabs' ) ); 157 | 158 | $suffix = SCRIPT_DEBUG ? '' : '.min'; 159 | $rtl = ! is_rtl() ? '' : '-rtl'; 160 | 161 | // enqueue the CSS for the admin 162 | wp_enqueue_style( 'mimi-admin', plugins_url( "css/admin{$rtl}{$suffix}.css", MADMIMI_PLUGIN_BASE ) ); 163 | 164 | } 165 | 166 | public function setup_help_tabs() { 167 | 168 | $screen = get_current_screen(); 169 | 170 | $screen->add_help_tab( array( 171 | 'title' => __( 'Overview', 'mad-mimi-sign-up-forms' ), 172 | 'id' => 'mimi-overview', 173 | 'content' => sprintf( 174 | '<h3>%1$s</h3> 175 | <p>%2$s</p> 176 | <ul> 177 | <li><strong>%3$s</strong>%4$s</li> 178 | <li><strong>%5$s</strong>%6$s</li> 179 | <li><strong>%7$s</strong>%8$s</li> 180 | </ul>', 181 | esc_html( 'Instructions', 'mad-mimi-sign-up-forms' ), 182 | sprintf( 183 | esc_html( 'Once the plugin is activated, you will be able to select and insert any of your Mad Mimi webforms right into your site. Setup is easy. Below, simply enter your account email address and API key (found in your Mad Mimi account [%s] area). Here are the 3 ways you can display a webform on your site:', 'mad-mimi-sign-up-forms' ), 184 | '<a target="_blank" href="https://madmimi.com/user/edit">https://madmimi.com/user/edit</a>' 185 | ), 186 | esc_html( 'Widget:', 'mad-mimi-sign-up-forms' ), 187 | esc_html( 'Go to Appearance → widgets and find the widget called “Mad Mimi Form” and drag it into the widget area of your choice. You can then add a title and select a form!', 'mad-mimi-sign-up-forms' ), 188 | esc_html( 'Shortcode:', 'mad-mimi-sign-up-forms' ), 189 | sprintf( 190 | esc_html( 'You can add a form to any post or page by adding the shortcode (ex. %s) in the page/post editor.', 'mad-mimi-sign-up-forms' ), 191 | '<code>[madmimi id=80326]</code>' 192 | ), 193 | esc_html( 'Template Tag:', 'mad-mimi-sign-up-forms' ), 194 | sprintf( 195 | esc_html( 'You can add the following template tag into any WordPress file: %1$s. Ex. %2$s', 'mad-mimi-sign-up-forms' ), 196 | '<code><?php madmimi_form( $form_id ); ?></code>', 197 | '<code><?php madmimi_form( 91 ); ?></code>' 198 | ) 199 | ), 200 | ) ); 201 | 202 | $screen->set_help_sidebar( sprintf( 203 | '<p><strong>%1$s</strong></p> 204 | <p><a href="https://madmimi.com" target="_blank">%2$s</a></p> 205 | <p><a href="https://help.madmimi.com" target="_blank">%3$s</a></p> 206 | <p><a href="https://blog.madmimi.com" target="_blank">%4$s</a></p> 207 | <p><a href="mailto:support@madmimi.com" target="_blank">%5$s</a></p>', 208 | esc_html( 'For more information:', 'mad-mimi-sign-up-forms' ), 209 | esc_html( 'Mad Mimi' ), 210 | esc_html__( 'Mad Mimi Help Docs', 'mad-mimi-sign-up-forms' ), 211 | esc_html__( 'Mad Mimi Blog', 'mad-mimi-sign-up-forms' ), 212 | esc_html__( 'Contact Mad Mimi', 'mad-mimi-sign-up-forms' ) 213 | ) ); 214 | 215 | } 216 | 217 | public function register_settings() { 218 | 219 | global $pagenow; 220 | 221 | // If no options exist, create them. 222 | if ( ! get_option( $this->slug ) ) { 223 | 224 | update_option( $this->slug, apply_filters( 'mimi_default_options', array( 225 | 'username' => '', 226 | 'api-key' => '', 227 | ) ) ); 228 | 229 | } 230 | 231 | register_setting( 'madmimi-options', $this->slug, array( $this, 'validate' ) ); 232 | 233 | // First, we register a section. This is necessary since all future options must belong to a 234 | add_settings_section( 235 | 'general_settings_section', 236 | esc_html__( 'Account Details', 'mad-mimi-sign-up-forms' ), 237 | array( 'Mad_Mimi_Settings_Controls', 'description' ), 238 | $this->slug 239 | ); 240 | 241 | add_settings_field( 242 | 'username', 243 | esc_html__( 'Mad Mimi Username', 'mad-mimi-sign-up-forms' ), 244 | array( 'Mad_Mimi_Settings_Controls', 'text' ), 245 | $this->slug, 246 | 'general_settings_section', 247 | array( 248 | 'id' => 'username', 249 | 'page' => $this->slug, 250 | 'description' => esc_html__( 'Your Mad Mimi username (email address)', 'mad-mimi-sign-up-forms' ), 251 | 'label_for' => "{$this->slug}-username", 252 | ) 253 | ); 254 | 255 | add_settings_field( 256 | 'api-key', 257 | esc_html__( 'Mad Mimi API Key', 'mad-mimi-sign-up-forms' ), 258 | array( 'Mad_Mimi_Settings_Controls', 'text' ), 259 | $this->slug, 260 | 'general_settings_section', 261 | array( 262 | 'id' => 'api-key', 263 | 'page' => $this->slug, 264 | 'description' => sprintf( 265 | '<a target="_blank" href="http://help.madmimi.com/where-can-i-find-my-api-key/">%s</a>', 266 | esc_html__( 'Where can I find my API key?', 'mad-mimi-sign-up-forms' ) 267 | ), 268 | 'label_for' => "{$this->slug}-api-key", 269 | ) 270 | ); 271 | 272 | $user_info = Mad_Mimi_Dispatcher::get_user_level(); 273 | 274 | add_settings_field( 275 | 'display_powered_by', 276 | '', 277 | array( 'Mad_Mimi_Settings_Controls', 'checkbox' ), 278 | $this->slug, 279 | 'general_settings_section', 280 | array( 281 | 'id' => 'display_powered_by', 282 | 'page' => $this->slug, 283 | 'label' => esc_html__( 'Display "Powered by Mad Mimi"?', 'mad-mimi-sign-up-forms' ), 284 | ) 285 | ); 286 | 287 | do_action( 'mimi_setup_settings_fields' ); 288 | 289 | } 290 | 291 | public function display_settings_page() { 292 | 293 | ?> 294 | 295 | <div class="wrap"> 296 | 297 | <h2><?php esc_html_e( 'Mad Mimi Settings', 'mad-mimi-sign-up-forms' ); ?></h2> 298 | 299 | <?php if ( ! Mad_Mimi_Settings_Controls::get_option( 'username' ) ) : ?> 300 | 301 | <div class="mimi-identity updated notice"> 302 | 303 | <h3><?php echo esc_html__( 'Enjoy the Mad Mimi Experience, first hand.', 'mad-mimi-sign-up-forms' ); ?></h3> 304 | 305 | <p><?php echo esc_html__( 'Add your Mad Mimi webform to your WordPress site! Easy to set up, the Mad Mimi plugin allows your site visitors to subscribe to your email list.', 'mad-mimi-sign-up-forms' ); ?></p> 306 | 307 | <p class="description"> 308 | <?php 309 | printf( 310 | /* translators: 1. Link to the Mad Mimi account signup. */ 311 | esc_html__( "Don't have a Mad Mimi account? Get one in less than 2 minutes! %s", 'mad-mimi-sign-up-forms' ), 312 | sprintf( 313 | '<a target="_blank" href="https://madmimi.com" class="button">%s</a>', 314 | esc_html__( 'Sign Up Now', 'mad-mimi-sign-up-forms' ) 315 | ) 316 | ); 317 | ?> 318 | </p> 319 | 320 | </div> 321 | 322 | <?php endif; ?> 323 | 324 | <form method="post" action="options.php"> 325 | 326 | <?php 327 | 328 | settings_fields( 'madmimi-options' ); 329 | 330 | do_settings_sections( $this->slug ); 331 | 332 | submit_button( __( 'Save Settings', 'mad-mimi-sign-up-forms' ) ); 333 | 334 | ?> 335 | 336 | <h3><?php esc_html_e( 'Available Forms', 'mad-mimi-sign-up-forms' ); ?></h3> 337 | 338 | <table class="wp-list-table widefat"> 339 | 340 | <thead> 341 | <tr> 342 | <th><?php esc_html_e( 'Form Name', 'mad-mimi-sign-up-forms' ); ?></th> 343 | <th><?php esc_html_e( 'Form ID', 'mad-mimi-sign-up-forms' ); ?></th> 344 | <th><?php esc_html_e( 'Shortcode', 'mad-mimi-sign-up-forms' ); ?></th> 345 | </tr> 346 | </thead> 347 | 348 | <tfoot> 349 | <tr> 350 | <th><?php esc_html_e( 'Form Name', 'mad-mimi-sign-up-forms' ); ?></th> 351 | <th><?php esc_html_e( 'Form ID', 'mad-mimi-sign-up-forms' ); ?></th> 352 | <th><?php esc_html_e( 'Shortcode', 'mad-mimi-sign-up-forms' ); ?></th> 353 | </tr> 354 | </tfoot> 355 | 356 | <tbody> 357 | 358 | <?php 359 | 360 | $forms = Mad_Mimi_Dispatcher::get_forms(); 361 | 362 | if ( $forms && ! empty( $forms->signups ) ) : 363 | 364 | foreach ( $forms->signups as $form ) : 365 | 366 | $edit_link = add_query_arg( array( 367 | 'action' => 'edit_form', 368 | 'form_id' => $form->id, 369 | ) ); 370 | 371 | ?> 372 | 373 | <tr> 374 | <td> 375 | 376 | <?php echo esc_html( $form->name ); ?> 377 | 378 | <div class="row-actions"> 379 | <span class="edit"> 380 | <a target="_blank" href="<?php echo esc_url( $edit_link ); ?>" title="<?php esc_attr_e( 'Opens in a new window', 'mad-mimi-sign-up-forms' ); ?>"><?php esc_html_e( 'Edit form in Mad Mimi', 'mad-mimi-sign-up-forms' ); ?></a> | 381 | </span> 382 | <span class="view"> 383 | <a target="_blank" href="<?php echo esc_url( $form->url ); ?>"><?php esc_html_e( 'Preview', 'mad-mimi-sign-up-forms' ); ?></a> 384 | </span> 385 | </div> 386 | </td> 387 | 388 | <td><code><?php echo absint( $form->id ); ?></code></td> 389 | <td><input type="text" class="code" value="[madmimi id=<?php echo absint( $form->id ); ?>]" onclick="this.select()" readonly /></td> 390 | 391 | </tr> 392 | 393 | <?php 394 | 395 | endforeach; 396 | 397 | else : 398 | 399 | ?> 400 | 401 | <tr> 402 | <td colspan="3"><?php esc_html_e( 'No forms found', 'mad-mimi-sign-up-forms' ); ?></td> 403 | </tr> 404 | 405 | <?php endif; ?> 406 | 407 | </tbody> 408 | </table> 409 | 410 | <br /> 411 | 412 | <p class="description"> 413 | <?php esc_html_e( 'Not seeing your form?', 'mad-mimi-sign-up-forms' ); ?> <a href="<?php echo esc_url( add_query_arg( 'action', 'refresh' ) ); ?>" class="button"><?php esc_html_e( 'Refresh Forms', 'mad-mimi-sign-up-forms' ); ?></a> 414 | </p> 415 | 416 | <?php if ( $this->mimi->debug ) : ?> 417 | 418 | <h3><?php esc_html_e( 'Debug', 'mad-mimi-sign-up-forms' ); ?></h3> 419 | <p> 420 | <a href="<?php echo esc_url( add_query_arg( 'action', 'debug-reset' ) ); ?>" class="button-secondary"><?php esc_html_e( 'Erase All Data', 'mad-mimi-sign-up-forms' ); ?></a> 421 | <a href="<?php echo esc_url( add_query_arg( 'action', 'debug-reset-transients' ) ); ?>" class="button-secondary"><?php esc_html_e( 'Erase Transients', 'mad-mimi-sign-up-forms' ); ?></a> 422 | </p> 423 | 424 | <?php endif; ?> 425 | 426 | </form> 427 | 428 | </div> 429 | 430 | <?php 431 | 432 | } 433 | 434 | public function validate( $input ) { 435 | 436 | // validate creds against the API 437 | if ( ! ( empty( $input['username'] ) || empty( $input['api-key'] ) ) ) { 438 | 439 | $data = Mad_Mimi_Dispatcher::fetch_forms( $input['username'], $input['api-key'] ); 440 | 441 | if ( ! $data ) { 442 | 443 | // credentials are incorrect 444 | add_settings_error( $this->slug, 'invalid-creds', __( 'The credentials are incorrect! Please verify that you have entered them correctly.', 'mad-mimi-sign-up-forms' ) ); 445 | 446 | return $input; // bail 447 | 448 | } elseif ( ! empty( $data->total ) ) { 449 | 450 | // test the returned data, and let the user know she's alright! 451 | add_settings_error( $this->slug, 'valid-creds', __( 'Connection with Mad Mimi has been established! You\'re all set!', 'mad-mimi-sign-up-forms' ), 'updated' ); 452 | 453 | } 454 | 455 | } else { 456 | 457 | // empty 458 | add_settings_error( $this->slug, 'invalid-creds', __( 'Please fill in the username and the API key first.', 'mad-mimi-sign-up-forms' ) ); 459 | 460 | } 461 | 462 | return $input; 463 | 464 | } 465 | } 466 | 467 | 468 | final class Mad_Mimi_Settings_Controls { 469 | 470 | public static function description() { 471 | 472 | ?> 473 | 474 | <p><?php esc_html_e( 'Please enter your Mad Mimi username and API Key in order to be able to create forms.', 'mad-mimi-sign-up-forms' ); ?></p> 475 | 476 | <?php 477 | 478 | } 479 | 480 | public static function select( $args ) { 481 | 482 | if ( empty( $args['options'] ) || empty( $args['id'] ) || empty( $args['page'] ) ) { 483 | 484 | return; 485 | 486 | } 487 | 488 | ?> 489 | 490 | <select id="<?php echo esc_attr( $args['id'] ); ?>" name="<?php echo esc_attr( sprintf( '%s[%s]', $args['page'], $args['id'] ) ); ?>"> 491 | 492 | <?php foreach ( $args['options'] as $name => $label ) : ?> 493 | 494 | <option value="<?php echo esc_attr( $name ); ?>" <?php selected( $name, (string) self::get_option( $args['id'] ) ); ?>> 495 | 496 | <?php echo esc_html( $label ); ?> 497 | 498 | </option> 499 | 500 | <?php endforeach; ?> 501 | 502 | </select> 503 | 504 | <?php 505 | 506 | } 507 | 508 | public static function text( $args ) { 509 | 510 | if ( empty( $args['id'] ) || empty( $args['page'] ) ) { 511 | 512 | return; 513 | 514 | } 515 | 516 | ?> 517 | 518 | <input type="text" name="<?php echo esc_attr( sprintf( '%s[%s]', $args['page'], $args['id'] ) ); ?>" 519 | id="<?php echo esc_attr( sprintf( '%s-%s', $args['page'], $args['id'] ) ); ?>" 520 | value="<?php echo esc_attr( self::get_option( $args['id'] ) ); ?>" class="regular-text code" /> 521 | 522 | <?php 523 | 524 | self::show_description( $args ); 525 | 526 | } 527 | 528 | public static function checkbox( $args ) { 529 | 530 | if ( empty( $args['id'] ) || empty( $args['page'] ) ) { 531 | 532 | return; 533 | 534 | } 535 | 536 | $name = sprintf( '%s[%s]', $args['page'], $args['id'] ); 537 | $label = isset( $args['label'] ) ? $args['label'] : ''; 538 | 539 | ?> 540 | 541 | <label for="<?php echo esc_attr( $name ); ?>"> 542 | <input type="checkbox" name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $name ); ?>" value="1" <?php checked( self::get_option( $args['id'] ) ); ?> /> 543 | <?php echo esc_html( $label ); ?> 544 | </label> 545 | 546 | <?php 547 | 548 | self::show_description( $args ); 549 | 550 | } 551 | 552 | public static function show_description( $field_args ) { 553 | 554 | if ( isset( $field_args['description'] ) ) : 555 | 556 | ?> 557 | 558 | <p class="description"><?php echo wp_kses_post( $field_args['description'] ); ?></p> 559 | 560 | <?php 561 | 562 | endif; 563 | 564 | } 565 | 566 | public static function get_option( $key = '' ) { 567 | 568 | $settings = get_option( 'mad-mimi-settings' ); 569 | 570 | return ( ! empty( $settings[ $key ] ) ) ? $settings[ $key ] : false; 571 | 572 | } 573 | 574 | } 575 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | <one line to give the program's name and a brief idea of what it does.> 294 | Copyright (C) <year> <name of author> 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | <signature of Ty Coon>, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | --------------------------------------------------------------------------------