initial docker setup

This commit is contained in:
GotPPay
2018-06-14 16:49:28 +02:00
parent bc80b7342e
commit b5f87f27f8
3023 changed files with 985078 additions and 1 deletions

View File

@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@@ -0,0 +1,105 @@
# MailChimp for Woocommerce Integration
In this article, youll learn how to connect MailChimp for WooCommerce.
## Before You Start
**Here are some things to know before you begin this process.**
- For the most up-to-date install instructions, read [Connect or Disconnect MailChimp for WooCommerce](http://kb.mailchimp.com/integrations/e-commerce/connect-or-disconnect-mailchimp-for-woocommerce).
- This plugin requires you to have the [WooCommerce plugin](https://wordpress.org/plugins/woocommerce) already installed and activated in WordPress.
- Your host environment must meet [WooCommerce's minimum requirements](https://docs.woocommerce.com/document/server-requirements), including PHP 7.0 or greater.
- We recommend you use this plugin in a staging environment before installing it on production servers.
- MailChimp for WooCommerce syncs the customers first name, last name, email address, and orders.
- WooCommerce customers who haven't signed up for marketing emails will appear in the Transactional portion of your list, and cannot be exported.
## A Note for Current WooCommerce Integration Users
This plugin supports our most powerful API 3.0 features, and is intended for users who have not yet integrated their WooCommerce stores with MailChimp. If your WooCommerce store is already integrated with MailChimp via an integration that runs on an older version of MailChimps API, consider your current sales volume before you make any changes that might disrupt business.
You can run this new integration at the same time as your current WooCommerce integration for MailChimp. However, data from the older integration will display separately in subscriber profiles, and cant be used with e-commerce features that require API 3.0.
## Task Roadmap
**Heres a brief overview of this multi-step process.**
- Install the plugin on your WordPress Admin site.
- Connect the plugin with your MailChimp API Key.
- Configure your list settings to complete the data sync process.
- Troubleshoot any sync or data feed issues by sharing logs with MailChimp support.
## Install the Plugin
**To install the plugin, follow these steps.**
1) Log in to your WordPress admin panel.
2) In the left navigation panel, click **Plugins**, and choose **Add New**.
![Add new](https://cloud.githubusercontent.com/assets/6547700/18677991/a7622bcc-7f28-11e6-8e8c-9bbdfa9861c7.png)
3) Click **Upload Plugin**.
![Upload](https://cloud.githubusercontent.com/assets/6547700/18677997/a76dab82-7f28-11e6-98e4-4309739cd840.png)
4) Click **Choose File** to select the ZIP file for the plugin, then click **Install Now**.
![Install Now](https://cloud.githubusercontent.com/assets/6547700/18677988/a760949c-7f28-11e6-9e13-13c23d044ad4.png)
5) Click **Activate Plugin**.
![Activate plugin](https://cloud.githubusercontent.com/assets/6547700/18677990/a760d7c2-7f28-11e6-8741-12c1efa7a991.png)
After you activate the plugin, youll be taken to the **Settings** page, where you will add your API key and configure your list settings.
## Configure and Sync
**To configure your MailChimp settings for WooCommerce customers and sync them to MailChimp, follow these steps.**
1) On the **Connect** tab, paste your MailChimp API key into the field, choose whether or not you want to send debugging logs to MailChimp, and click **Save all changes**. To learn how to generate a MailChimp API Key, read [About API Keys](http://kb.mailchimp.com/integrations/api-integrations/about-api-keys).
![API key](https://cloud.githubusercontent.com/assets/19805049/18877771/3fca90e8-849c-11e6-9e3a-161a7b3936dd.png)
2) Navigate to the **Store Settings** tab.
![Store Settings](https://cloud.githubusercontent.com/assets/6547700/18677998/a76e5640-7f28-11e6-9fd3-d66949fa1413.png)
3) Enter the contact and location details for your WooCommerce Store, and click **Save all changes**.
![Save all changes](https://cloud.githubusercontent.com/assets/6547700/18677996/a76d126c-7f28-11e6-9150-4b289d20f057.png)
4) Navigate to the **List Settings** tab.
![List Settings tab](https://cloud.githubusercontent.com/assets/19805049/18878446/961221d0-849e-11e6-99bb-175c22bf921e.png)
5) Choose the list you want to sync, decide whether or not you want to auto-subscribe existing customers, set the subscribe message you want customers to see at checkout, and click **Save all changes**.
![Save all changes](https://cloud.githubusercontent.com/assets/19805049/18877772/3fd24162-849c-11e6-8442-79ec4550b8ac.png)
All set! When you click **Save all changes**, well start syncing your WooCommerce customers to MailChimp. To view progress, check the **Sync Status** tab.
If you have no lists in your MailChimp account, you will be given the option to create a new list on the **List Defaults** tab. To create a new list, set your list defaults, and click **Save all Changes** when youre done. Well create a MailChimp list for you, and begin the data sync.
![List Defaults tab](https://cloud.githubusercontent.com/assets/19805049/18956260/cffd3926-8628-11e6-9c68-9fe3c964c75c.png)
## Next Steps
After you connect, you can do a lot with the the data you collect, like build segments, send Automation workflows, track purchases, and view results.
Find out everything MailChimp has to offer in our article, [How to Use MailChimp for E-Commerce](http://kb.mailchimp.com/integrations/e-commerce/how-to-use-mailchimp-for-e-commerce).
# Deactivate or Delete the Plugin
When you deactivate MailChimp for WooCommerce, it stops the sync but doesnt remove the plugin. You can always re-activate the sync, which will backfill data at a later point in time.
To deactivate MailChimp for WooCommerce, follow these steps.
1) Log in to your WordPress admin panel.
2) In the left navigation panel, click **Plugins**, and choose **Installed Plugins**.
![Installed Plugins](https://cloud.githubusercontent.com/assets/6547700/18677993/a76542ee-7f28-11e6-99dd-cfd6c1f5c24a.png)
3) Click the box next to the MailChimp for WooCommerce plugin, and click **Deactivate**.
![Deactivate](https://cloud.githubusercontent.com/assets/6547700/18677992/a762b844-7f28-11e6-9679-8d6c6a1d731d.png)
After you deactivate the plugin, you will have the option to **Delete** it. If you delete the plugin, you will retain customers email addresses in your list, but remove all associated e-commerce data.

View File

@@ -0,0 +1,232 @@
=== MailChimp for WooCommerce ===
Contributors: ryanhungate, MailChimp
Tags: ecommerce,email,workflows,mailchimp
Donate link: https://mailchimp.com
Requires at least: 4.3
Tested up to: 4.9.5
Stable tag: 2.1.7
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Connect your store to your MailChimp list to track sales, create targeted emails, send abandoned cart emails, and more.
== Description ==
Join the 17 million customers who use MailChimp, the world's largest marketing automation platform, to develop their e-commerce marketing strategy. With the official MailChimp for WooCommerce integration, your customers and their purchase data are automatically synced with your MailChimp account, making it easy to send targeted campaigns, automatically follow up with customers post-purchase, recommend products, recover abandoned carts, and measure the ROI of your marketing efforts. And it's completely free.
With MailChimp for WooCommerce, youll have the power to:
- Sync list and purchase data.
- Set up marketing automations to remind customers about items they left in their cart or viewed on your site, win back lapsed customers, and follow up post-purchase. (Now available for free accounts!)
- Showcase product recommendations.
- Track and segment customers based on purchase history and purchase frequency.
- View detailed data on your marketing performance in your MailChimp Dashboard.
- Find new customers, connect with current ones, and drive them all to your website with [Facebook](https://mailchimp.com/features/facebook-ads/) and [Instagram](https://mailchimp.com/features/instagram-ads/) ads. Then, set up [Google remarketing](https://mailchimp.com/features/google-remarketing-ads/) ads to turn your site visitors into shoppers.
- Automatically embed a pop-up form that converts your website visitors to subscribers.
- Add discount codes created in WooCommerce to your emails and automations with a Promo Code content block
- Create beautiful landing pages that make it easy to highlight your products, promote a sale or giveaway, and grow your list.
###Important Notes
This plugin supports our most powerful API 3.0 features, and is intended for users who have not yet integrated their WooCommerce stores with MailChimp.
You can run this new integration at the same time as your current WooCommerce integration for MailChimp. However, data from the older integration will display separately in subscriber profiles, and cant be used with e-commerce features that require API 3.0.
WordPress.com compatibility is limited to Business tier users only.
=== Installation ===
###Before You Start
Here are some things to know before you begin this process.
- This plugin requires you to have the [WooCommerce plugin](https://woocommerce.com/) already installed and activated in WordPress.
- Your hosting environment must meet [WooCommerce's minimum requirements](https://docs.woocommerce.com/document/server-requirements), including PHP 7.0 or greater.
- We recommend you use this plugin in a staging environment before installing it on production servers. To learn more about staging environments, [check out these related Wordpress plugins](https://wordpress.org/plugins/search.php?q=staging).
- MailChimp for WooCommerce syncs the customers first name, last name, email address, and orders.
- WooCommerce customers who haven't signed up for marketing emails will appear in the **Transactional** portion of your list, and cannot be exported.
###Task Roadmap
Youll need to do a few things to connect your WooCommerce store to MailChimp.
- Download the plugin.
- Install the plugin on your WordPress Admin site.
- Connect the plugin with your MailChimp API Key.
- Configure your list settings to complete the data sync process.
###Advanced Queue Setup In CLI mode
To optimize the performance of your MailChimp integration - it is recommended that you run the queue in CLI mode.
First define a constant in your config file
`define('DISABLE_WP_HTTP_WORKER', true);`
You have 2 options to run this process:
1. On a cron schedule every minute:
`* * * * * /usr/bin/wp --url=http://yourdomain.com --path=/full/path/to/install/ queue listen`
2. Using a process manager like Monit or Supervisord:
`/usr/bin/wp --url=http://yourdomain.com --path=/full/path/to/install/ queue listen`
== Changelog ==
= 2.1.7 =
* fix Queue_Command filepath in autoloader
= 2.1.6 =
* moved to an autoloader for performance enhancement
* flush database tables on un-installation to assist with stale records in the queue
* turn on standard debugging by default to help troubleshoot issues
* moved the plugin button to the left main navigation
* allow store owners to select the image size being used for products
* fix paypal new order bug where it did not send on initial placement
* add additional configuration success checks for the plugin being configured before pushing any jobs into the queue
* fix the multisite network activation issue
* hide the opt in checkbox for already logged in customers that were previously subscribed
* miscellaneous UI enhancements
= 2.1.5 =
* is_configured filters applied before certain jobs were firing and failing.
= 2.1.5 =
* added support for Polish (zloty - zł) and Moldovan Leu currencies
* update currency code for Belarusian Rouble
* queue performance enhancement
= 2.1.4 =
* updated wordpress compatibility
* updated sync details tab to show more informative stats
* queue job processing performance enhancement
* added an integrity check for queued jobs that were not getting processed
= 2.1.3 =
* Fix subscriber status for repeat transactional customers to stay transactional.
* Remove shipping and billing address requirements for order submission.
* Do not unsubscribe someone who has previously subscribed when unchecking the newsletter sign up box.
* Update newsletter checkbox style to be consistent with WooCommerce styles.
* Make sure WooCommerce plugin is running before running any plugin code.
* Fix compatibility issue with WP-Cron
= 2.1.2 =
* Fix store deletion on plugin deactivation
* Correct shipping name is now used on order notifications.
* Admin orders are now handled appropriately.
* Skip incomplete or cancelled orders from being submitted when new.
* fix hidden or inactive products from being recommended.
= 2.1.1 =
* To address performance issues previously reported, we've changed the action hook of "woocommerce_cart_updated" to use a filter "woocommerce_update_cart_action_cart_updated"
= 2.1.0 =
* Added Promo Code support.
= 2.0.2 =
* Added new logs feature to help troubleshoot isolated sync and data feed issues.
* Fixed bug with setting customers as Transactional during checkout if they had already opted in previously.
* Fixed bug where abandoned cart automation still fired after a customer completed an order.
= 2.0.1 =
* Added support for "Connected Site" scripts.
* Made physical address a required field for store setup.
* Fixed order, cart timestamps to begin using UTC.
= 2.0 =
* Support WooComerce 3.0
* Support for manually uploaded WooCommerce
* Fix for sync issues
* Fix for guest orders sync issue
* Remove MailChimp debug logger
= 1.1.1 =
* Support for site url changes
* Fix for WP Version 4.4 compatibility issues
= 1.1.0 =
* Fix for persisting opt-in status
* Pass order URLs to MailChimp
* Pass partial refund status to MailChimp
= 1.0.9 =
* billing and shipping address support for orders
= 1.0.8 =
* add landing_site, financial status and discount information for orders
* fix to support php 5.3
= 1.0.7 =
* add options to move, hide and change defaults for opt-in checkbox
* add ability to re-sync and display connection details
* support for subscriptions without orders
* additional small fixes and some internal logging removal
= 1.0.6 =
* fixed conflict with the plugin updater where the class could not be loaded correctly.
* fixed error validation for store name.
* fixed cross device abandoned cart url's
= 1.0.4 =
* fix for Abandoned Carts without cookies
= 1.0.3 =
* fixed cart posts on dollar amounts greater than 1000
= 1.0.2 =
* title correction for Product Variants
* added installation checks for WooCommerce and phone contact info
* support for free orders
= 1.0 =
* added is_synicng flag to prevent sends during backfill
* fix for conflicts with Gravity Forms Pro and installation issues
* skip all Amazon orders
* allow users to set opt-in for pre-existing customers during first sync
* add Plugin Updater
= 0.1.22 =
* flag quantity as 1 if the product does not manage inventory
= 0.1.21 =
* php version check to display warnings < 5.5
= 0.1.19 =
* fix campaign tracking on new orders
= 0.1.18 =
* check woocommerce dependency before activating the plugin
= 0.1.17 =
* fix php version syntax errors for array's
= 0.1.16 =
* fix namespace conflicts
* fix free order 0.00 issue
* fix product variant naming issue
= 0.1.15 =
* adding special MailChimp header to requests
= 0.1.14 =
* removing jquery dependencies
= 0.1.13 =
* fixing a number format issue on total_spent
= 0.1.12 =
* skipping orders placed through amazon due to seller agreements
= 0.1.11 =
* removed an extra debug log that was not needed
= 0.1.10 =
* altered debug logging and fixed store settings validation requirements
= 0.1.9 =
* using fallback to stream context during failed patch requests
= 0.1.8 =
* fixing http request header for larger patch requests
= 0.1.7 =
* fixing various bugs with the sync and product issues.
= 0.1.2 =
* fixed admin order update hook.

View File

@@ -0,0 +1,889 @@
<?php
/**
* The admin-specific functionality of the plugin.
*
* @link https://mailchimp.com
* @since 1.0.1
*
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/admin
*/
/**
* The admin-specific functionality of the plugin.
*
* Defines the plugin name, version, and two examples hooks for how to
* enqueue the admin-specific stylesheet and JavaScript.
*
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/admin
* @author Ryan Hungate <ryan@vextras.com>
*/
class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
/**
* @return MailChimp_WooCommerce_Admin
*/
public static function connect()
{
$env = mailchimp_environment_variables();
return new self('mailchimp-woocommerce', $env->version);
}
/**
* Initialize the class and set its properties.
*
* @since 1.0.0
* @param string $plugin_name The name of this plugin.
* @param string $version The version of this plugin.
*/
public function __construct( $plugin_name, $version ) {
$this->plugin_name = $plugin_name;
$this->version = $version;
}
/**
* Register the stylesheets for the admin area.
*
* @since 1.0.0
*/
public function enqueue_styles() {
wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/mailchimp-woocommerce-admin.css', array(), $this->version, 'all' );
}
/**
* Register the JavaScript for the admin area.
*
* @since 1.0.0
*/
public function enqueue_scripts() {
wp_enqueue_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/mailchimp-woocommerce-admin.js', array( 'jquery' ), $this->version, false );
}
/**
* Register the administration menu for this plugin into the WordPress Dashboard menu.
*
* @since 1.0.0
*/
public function add_plugin_admin_menu() {
add_menu_page(
'MailChimp - WooCommerce Setup',
'MailChimp',
'manage_options',
$this->plugin_name,
array($this, 'display_plugin_setup_page'),
'data:image/svg+xml;base64,'.$this->mailchimp_svg()
);
}
/**
* @return string
*/
protected function mailchimp_svg()
{
return base64_encode('<?xml version="1.0" encoding="UTF-8"?>
<svg width="111px" height="116px" viewBox="0 0 111 116" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 50 (54983) - http://www.bohemiancoding.com/sketch -->
<title>Group</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group">
<path d="M76.5859,0.7017 L76.5849,0.7017 C71.6089,0.7017 65.7009,2.4987 59.7709,5.7927 C58.6459,4.8877 57.3339,3.8317 57.2839,3.7927 C55.0919,2.0667 52.4549,1.1907 49.4489,1.1897 C39.2019,1.1897 27.9399,11.1957 22.1389,17.1607 C12.9849,26.5727 5.6129,37.8427 2.4179,47.3087 C-1.5161,58.9627 1.8869,64.6287 5.4329,67.3307 L8.1899,69.4387 C6.2259,78.2517 11.1159,87.7027 19.6639,90.8437 C21.2849,91.4397 22.9629,91.7857 24.6639,91.8777 C28.2049,97.4237 41.6679,115.5347 66.4699,115.5417 C80.1529,115.5417 91.7799,109.9377 100.1089,99.3337 C105.7329,92.1747 108.1719,84.8867 108.8149,82.7097 C109.6379,81.3307 111.6759,77.2977 110.0739,73.4267 L110.0479,73.3637 L110.0189,73.3007 C109.1609,71.4697 107.6859,70.0227 105.8399,69.1577 C105.6629,68.5617 105.4829,68.0447 105.3149,67.6077 C106.7299,65.4787 107.0949,62.8477 106.2809,60.4207 C105.4089,57.8187 103.3169,55.7857 100.6029,54.8587 C98.0479,52.5407 95.7049,51.3697 93.9629,50.4987 L93.6009,50.3177 C93.1359,50.0857 92.8879,49.9617 92.6859,49.8647 C92.6089,49.1767 92.5369,48.3707 92.4619,47.5407 C92.2669,45.3737 92.0449,42.9177 91.6319,40.8417 C90.9369,37.3437 89.4899,34.6077 87.3279,32.6967 C86.8749,31.7957 86.2689,30.7457 85.4899,29.7127 C91.4609,19.6007 92.1439,10.1877 87.1759,4.8097 C84.6939,2.1217 81.0319,0.7017 76.5859,0.7017 M76.5859,3.7017 C80.0809,3.7017 83.0039,4.7137 84.9719,6.8447 C89.3919,11.6297 87.8029,20.7677 81.7689,30.0187 C83.0659,31.2507 84.1419,32.9257 84.9099,34.5887 C86.8279,36.0687 88.0709,38.3197 88.6899,41.4277 C89.3779,44.8837 89.5209,49.8057 89.9519,51.9207 C91.5789,52.6557 90.8869,52.3157 92.6209,53.1827 C94.4309,54.0867 96.6339,55.1877 99.0679,57.5307 C103.3969,58.6147 105.0489,63.2157 102.5169,66.3567 C102.4479,66.4407 102.1429,66.8027 101.8259,67.1627 C101.9009,67.3627 102.7319,68.7067 103.3309,71.4447 C105.1239,71.8687 106.5529,72.9727 107.3019,74.5737 C108.5989,77.7077 106.0479,81.4777 106.0479,81.4777 C105.9629,81.7547 97.9549,112.5417 66.4849,112.5417 L66.4709,112.5417 C39.2589,112.5337 26.3599,88.8807 26.3599,88.8807 C26.0989,88.8947 25.8389,88.9027 25.5799,88.9027 C23.8749,88.9027 22.2309,88.5907 20.6979,88.0277 C12.7149,85.0947 8.8839,75.9607 11.6389,68.2977 L7.2499,64.9447 C-8.0381,53.2977 29.3809,4.1887 49.4489,4.1897 C51.6919,4.1907 53.7189,4.8037 55.4309,6.1517 C55.5169,6.2197 59.4949,9.4217 59.4949,9.4217 C65.6079,5.7087 71.6629,3.7017 76.5849,3.7017 L76.5859,3.7017" id="Fill-40" fill="#FFFFFF"></path>
<path d="M79.1367,27.5845 L79.1377,27.5835 C79.1297,27.5625 79.0647,27.3825 79.0387,27.3335 C78.0087,25.1455 75.6057,23.6175 73.4647,23.0045 C73.8397,23.3955 74.3827,24.1095 74.6037,24.5345 C72.9877,23.4245 70.8397,22.4465 68.5987,21.9825 C68.5987,21.9825 68.8657,22.1745 68.9117,22.2165 C69.3587,22.6325 69.9527,23.2905 70.1967,23.8555 C68.0547,22.9955 65.3467,22.5135 63.0297,22.9595 C62.9957,22.9655 62.7397,23.0265 62.7397,23.0265 C62.7397,23.0265 63.0407,23.1015 63.1087,23.1215 C63.8767,23.3495 64.9737,23.8175 65.4567,24.4595 C61.6097,23.7825 57.3767,24.5315 55.0947,25.8085 C55.3887,25.7955 55.3857,25.7945 55.6337,25.8015 C56.4727,25.8235 58.1647,25.9375 58.8747,26.3895 C56.4487,26.8825 52.9367,27.9685 51.0457,29.5945 C51.3787,29.5555 53.2737,29.3145 54.0487,29.4385 C43.6427,35.3935 38.9067,44.3965 38.9067,44.3965 C41.9747,40.3985 45.9547,36.5505 51.3827,33.0325 C63.2387,25.3485 75.0797,24.4655 79.1367,27.5845" id="Fill-42" fill="#FFFFFE"></path>
<path d="M27.9473,80.7656 C26.3263,80.8026 25.4413,79.7896 25.6003,79.5686 C25.6743,79.4626 25.9213,79.5096 26.3013,79.5656 C28.3663,79.8866 29.6193,78.6266 29.9223,77.3066 C29.9263,77.2856 30.0083,76.9336 30.0043,76.6886 C30.0203,76.4766 29.9973,76.2606 29.9653,76.0676 C29.7203,74.7016 28.1543,74.4446 27.1473,73.3576 C26.2433,72.3756 26.4223,71.1166 26.9893,70.5126 C27.6723,69.8396 28.6483,70.0846 28.6353,70.3236 C28.6343,70.4496 28.3993,70.5446 28.1073,70.7446 C27.7283,71.0116 27.6783,71.2696 27.7743,71.7126 C27.8393,71.9556 27.9473,72.1156 28.1813,72.2996 C29.0283,72.9756 31.3043,73.4466 31.7183,75.7366 C32.1753,78.3656 30.2603,80.7166 27.9473,80.7656 M24.3623,68.1646 C23.9123,68.2606 24.1643,68.2056 23.7193,68.3306 C23.6503,68.3506 23.5873,68.3696 23.5323,68.3926 C23.3923,68.4586 23.2633,68.5036 23.1393,68.5696 C23.0363,68.6266 22.1513,69.0216 21.4313,69.9016 C20.4633,71.1046 20.1113,72.6796 20.1703,74.1956 C20.2283,75.6676 20.6603,76.4826 20.7403,76.6816 C21.0743,77.4006 20.2913,77.5476 19.5763,76.7756 L19.5743,76.7736 C19.0033,76.1676 18.6353,75.2456 18.4573,74.4276 L18.4573,74.4266 L18.4573,74.4276 C17.7313,71.0386 19.2443,67.6326 22.7353,66.2716 C22.9303,66.1946 23.1583,66.1466 23.3423,66.0926 L23.3413,66.0936 C23.6973,65.9876 24.9743,65.7286 26.2723,65.9306 C27.6973,66.1516 28.9563,66.8666 29.7543,67.7936 L29.7563,67.7956 C30.3703,68.4946 30.8333,69.4786 30.7503,70.3546 L30.7503,70.3566 C30.7193,70.7206 30.5573,71.2436 30.2293,71.3786 C30.1073,71.4286 29.9853,71.4026 29.8993,71.3186 C29.6623,71.0856 29.8453,70.6076 29.2663,69.7876 C28.4993,68.6996 26.7633,67.6566 24.3623,68.1646 M34.8423,74.1896 C34.9993,71.6386 34.5973,69.1156 33.8133,66.7166 C33.8133,66.7166 33.4683,68.1466 32.7823,69.8896 C32.1243,64.3126 29.7833,63.1316 29.7833,63.1316 C28.4263,62.5036 26.9273,62.1546 25.3503,62.1546 C19.2683,62.1546 14.3393,67.3446 14.3393,73.7476 C14.3393,80.1516 19.2683,85.3416 25.3503,85.3416 C32.2013,85.3416 37.4013,78.8196 36.1913,71.6936 C36.1913,71.6936 35.4923,73.3246 34.8423,74.1896" id="Fill-44" fill="#FFFFFF"></path>
<path d="M55.2637,15.4038 C54.6187,15.8608 54.0497,16.2798 53.5687,16.6428 L50.2657,13.8778 L55.2637,15.4038 Z M57.7737,13.7038 C57.2307,14.0548 56.7147,14.3998 56.2307,14.7308 L55.3507,11.6728 L57.7737,13.7038 Z M18.5667,60.1648 L18.3907,60.1708 C22.0977,47.2248 32.0597,33.9258 42.2127,25.2628 C44.7447,23.1018 49.8377,19.6738 49.8377,19.6738 L44.0837,14.6028 L43.6637,11.6738 L51.5817,18.2108 C51.5807,18.2118 51.5797,18.2128 51.5797,18.2128 C51.2217,18.5058 50.8627,18.8068 50.5027,19.1138 C49.7227,19.7818 48.9407,20.4808 48.1597,21.2078 C47.0237,22.2638 45.8907,23.3788 44.7697,24.5368 C42.3547,27.0338 39.9957,29.7368 37.7857,32.5168 C33.8777,37.4318 32.2517,39.7248 29.7837,44.3968 C29.7727,44.4108 43.2807,28.2128 46.6437,24.8758 C52.8167,18.7528 62.9197,11.9348 63.0257,11.8738 C67.3387,9.2338 70.9807,7.6838 73.9687,7.0118 C69.0587,7.5128 63.8067,10.0368 59.6847,12.5108 C59.6777,12.5048 53.6927,7.4468 53.6847,7.4408 L51.4907,8.2808 L52.6747,12.5858 L51.2097,12.1118 L50.7927,10.4258 L51.4907,8.2808 C43.5097,6.3878 25.9397,19.6458 15.3837,36.4458 C11.1127,43.2428 5.1097,55.2008 8.5607,61.0238 C9.1437,62.0148 13.2437,65.0248 13.2867,65.0358 C14.8877,62.8148 16.7207,61.1818 18.5667,60.1648 Z" id="Fill-46" fill="#FFFFFF"></path>
<path d="M62.7568,61.0156 C62.6058,60.8996 62.7548,60.4276 63.2788,59.9196 C63.7368,59.4816 64.2098,59.2346 64.7548,59.0046 C64.8408,58.9686 64.9288,58.9356 65.0208,58.9126 C65.2728,58.8456 65.5278,58.7596 65.8048,58.7176 C68.0218,58.3406 69.6438,59.5706 69.4328,59.9276 C69.3378,60.0936 68.9278,60.0566 68.3158,60.0156 C67.0468,59.9276 65.7148,59.9486 63.8318,60.7316 C63.2698,60.9576 62.9058,61.1346 62.7568,61.0156 M60.2968,57.2016 C59.4678,57.5176 58.8788,57.7626 58.5968,57.7206 C58.1368,57.6526 58.5818,56.8096 59.5878,55.9936 C61.6108,54.3786 64.3888,53.8776 66.7638,54.7616 C67.8028,55.1446 68.9698,55.9076 69.5798,56.8006 C69.8118,57.1386 69.8738,57.3946 69.7798,57.4996 C69.5938,57.7176 68.9288,57.4236 67.9448,57.0406 C65.4308,56.1026 63.5768,55.9596 60.2968,57.2016 M76.5508,58.4516 C76.8948,57.8226 77.8728,57.6966 78.7348,58.1676 C79.5958,58.6406 80.0158,59.5326 79.6708,60.1616 C79.3268,60.7886 78.3488,60.9156 77.4868,60.4436 C76.6258,59.9716 76.2058,59.0786 76.5508,58.4516 M80.1828,47.5176 L80.1818,47.5176 C80.1828,47.5176 80.1828,47.5176 80.1838,47.5176 C81.4978,47.0616 83.2388,50.4286 83.3188,53.4166 C82.2798,52.8976 81.0598,52.6766 79.8038,52.7856 C79.4878,51.8236 79.3368,50.9166 79.2998,49.9356 C79.2828,49.1196 79.4128,47.7686 80.1828,47.5176 M84.3258,57.6766 C84.1928,58.5366 83.5748,59.1536 82.9488,59.0556 C82.3218,58.9576 81.9228,58.1826 82.0578,57.3236 C82.1918,56.4636 82.8078,55.8466 83.4348,55.9446 C84.0608,56.0416 84.4598,56.8186 84.3258,57.6766 M101.6328,74.9486 C100.7498,74.9486 100.0828,75.1816 100.0828,75.1816 C100.0828,75.1816 100.0938,71.5046 98.3928,68.6416 C97.0818,70.1166 93.4438,73.0366 88.6678,75.3036 C84.1908,77.4296 78.2158,79.2906 70.8118,79.5376 C68.7378,79.6276 67.4548,79.2896 66.7338,81.7066 C66.6748,81.9226 66.6378,82.1646 66.6178,82.4116 C74.7338,84.9606 87.5698,79.9886 88.8158,79.6996 C88.8678,79.6876 88.9008,79.6806 88.9318,79.6796 C89.7358,79.7446 82.0398,84.5996 71.3608,84.5996 C69.5578,84.5996 68.0038,84.4426 66.7768,84.1966 C67.3608,86.1986 68.8858,87.0806 70.8948,87.5476 C72.4178,87.9026 74.0348,87.9366 74.0348,87.9366 C88.8308,88.3516 101.0058,76.8876 101.5088,76.2986 C101.5088,76.2986 101.3758,76.6096 101.3608,76.6446 C99.1918,81.5226 86.6338,90.3676 74.1338,90.1146 L74.0928,90.1276 C71.1948,90.1176 67.6718,89.3706 65.8408,87.1006 C62.9438,83.5076 64.4468,77.5356 69.0648,77.3946 C69.0698,77.3946 70.1318,77.3696 70.6048,77.3586 C82.0368,77.0066 92.2948,72.8066 99.6398,64.0356 C100.6498,62.7816 99.5218,61.0576 97.3328,61.0046 L97.3018,61.0046 C97.3018,61.0046 97.2888,60.9906 97.2808,60.9826 C94.6868,58.2026 92.4048,57.2216 90.3758,56.1906 C86.1208,54.0236 86.5218,55.8956 85.5308,45.3816 C85.2638,42.5476 84.7268,38.6816 82.2368,37.1996 C81.5838,36.8106 80.8708,36.6446 80.1298,36.6446 C79.3988,36.6446 79.0418,36.7936 78.8978,36.8256 C77.5338,37.1276 76.7578,37.9016 75.7858,38.7966 C71.1948,43.0306 67.5268,41.8816 62.0488,41.8326 C56.9048,41.7876 52.3628,45.3756 51.4948,50.8866 L51.4928,50.8896 C51.0708,53.7746 51.3448,56.7046 51.7958,58.0226 C51.7958,58.0226 50.4008,57.0936 49.7348,56.2716 C50.5398,61.3056 55.1328,64.5956 55.1328,64.5956 C54.4088,64.7616 53.3688,64.6926 53.3688,64.6926 C53.3728,64.6966 55.9898,66.7666 58.2618,67.4886 C57.6698,67.8566 54.6758,70.8106 53.1318,74.8776 C51.6878,78.6836 52.2758,83.2536 52.2758,83.2536 L53.5298,81.3826 C53.5298,81.3826 52.7108,85.5516 54.2968,89.5886 C54.8228,88.3886 55.9738,86.2446 55.9738,86.2446 C55.9738,86.2446 55.7908,90.7206 57.9458,94.3866 C58.0018,93.5406 58.3248,91.3866 58.3248,91.3866 C58.3248,91.3866 59.5628,95.2086 62.4188,97.8816 C67.7678,102.6276 81.9298,103.4856 92.7078,95.0156 C101.2448,88.3076 102.7358,80.2286 102.8788,79.9506 C104.9798,77.4306 104.4078,74.9486 101.6328,74.9486" id="Fill-48" fill="#FFFFFF"></path>
</g>
</g>
</svg>');
}
/**
* Add settings action link to the plugins page.
*
* @since 1.0.0
*/
public function add_action_links($links) {
$settings_link = array(
'<a href="' . admin_url( 'options-general.php?page=' . $this->plugin_name ) . '">' . __('Settings', $this->plugin_name) . '</a>',
);
return array_merge($settings_link, $links);
}
/**
* Render the settings page for this plugin.
*
* @since 1.0.0
*/
public function display_plugin_setup_page() {
include_once( 'partials/mailchimp-woocommerce-admin-tabs.php' );
}
/**
*
*/
public function options_update() {
$this->handle_abandoned_cart_table();
register_setting($this->plugin_name, $this->plugin_name, array($this, 'validate'));
}
/**
* Depending on the version we're on we may need to run some sort of migrations.
*/
public function update_db_check() {
// grab the current version set in the plugin variables
$version = mailchimp_environment_variables()->version;
// grab the saved version or default to 1.0.3 since that's when we first did this.
$saved_version = get_site_option('mailchimp_woocommerce_version', '1.0.3');
// if the saved version is less than the current version
if (version_compare($version, $saved_version) > 0) {
// resave the site option so this only fires once.
update_site_option('mailchimp_woocommerce_version', $version);
}
}
/**
* We need to do a tidy up function on the mailchimp_carts table to
* remove anything older than 30 days.
*
* Also if we don't have the configuration set, we need to create the table.
*/
protected function handle_abandoned_cart_table()
{
global $wpdb;
if (get_site_option('mailchimp_woocommerce_db_mailchimp_carts', false)) {
// need to tidy up the mailchimp_cart table and make sure we don't have anything older than 30 days old.
$date = gmdate( 'Y-m-d H:i:s', strtotime(date ("Y-m-d") ."-30 days"));
$sql = $wpdb->prepare("DELETE FROM {$wpdb->prefix}mailchimp_carts WHERE created_at <= %s", $date);
$wpdb->query($sql);
} else {
// create the table for the first time now.
$charset_collate = $wpdb->get_charset_collate();
$table = "{$wpdb->prefix}mailchimp_carts";
$sql = "CREATE TABLE IF NOT EXISTS $table (
id VARCHAR (255) NOT NULL,
email VARCHAR (100) NOT NULL,
user_id INT (11) DEFAULT NULL,
cart text NOT NULL,
created_at datetime NOT NULL
) $charset_collate;";
if (($result = $wpdb->query($sql)) > 0) {
update_site_option('mailchimp_woocommerce_db_mailchimp_carts', true);
}
}
}
/**
* @param $input
* @return array
*/
public function validate($input) {
$active_tab = isset($input['mailchimp_active_tab']) ? $input['mailchimp_active_tab'] : null;
if (empty($active_tab)) {
return $this->getOptions();
}
switch ($active_tab) {
case 'api_key':
$data = $this->validatePostApiKey($input);
break;
case 'store_info':
$data = $this->validatePostStoreInfo($input);
break;
case 'campaign_defaults' :
$data = $this->validatePostCampaignDefaults($input);
break;
case 'newsletter_settings':
$data = $this->validatePostNewsletterSettings($input);
break;
case 'sync':
// remove all the pointers to be sure
$service = new MailChimp_Service();
$service->removePointers(true, true);
$this->startSync();
$this->showSyncStartedMessage();
$this->setData('sync.config.resync', true);
break;
case 'logs':
if (isset($_POST['mc_action']) && in_array($_POST['mc_action'], array('view_log', 'remove_log'))) {
wp_redirect('options-general.php?page=mailchimp-woocommerce&tab=logs');
exit();
}
$data = array(
'mailchimp_logging' => isset($input['mailchimp_logging']) ? $input['mailchimp_logging'] : 'none',
);
break;
}
return (isset($data) && is_array($data)) ? array_merge($this->getOptions(), $data) : $this->getOptions();
}
/**
* STEP 1.
*
* Handle the 'api_key' tab post.
*
* @param $input
* @return array
*/
protected function validatePostApiKey($input)
{
$data = array(
'mailchimp_api_key' => isset($input['mailchimp_api_key']) ? $input['mailchimp_api_key'] : false,
'mailchimp_debugging' => isset($input['mailchimp_debugging']) ? $input['mailchimp_debugging'] : false,
'mailchimp_account_info_id' => null,
'mailchimp_account_info_username' => null,
);
$api = new MailChimp_WooCommerce_MailChimpApi($data['mailchimp_api_key']);
$valid = true;
if (empty($data['mailchimp_api_key']) || !($profile = $api->ping(true))) {
unset($data['mailchimp_api_key']);
$valid = false;
if (!$profile) {
add_settings_error('mailchimp_store_settings', '', 'API Key Invalid');
}
}
// tell our reporting system whether or not we had a valid ping.
$this->setData('validation.api.ping', $valid);
$data['active_tab'] = $valid ? 'store_info' : 'api_key';
if ($valid && isset($profile) && is_array($profile) && array_key_exists('account_id', $profile)) {
$data['mailchimp_account_info_id'] = $profile['account_id'];
$data['mailchimp_account_info_username'] = $profile['username'];
}
return $data;
}
/**
* STEP 2.
*
* Handle the 'store_info' tab post.
*
* @param $input
* @return array
*/
protected function validatePostStoreInfo($input)
{
$data = $this->compileStoreInfoData($input);
if (!$this->hasValidStoreInfo($data)) {
if ($this->hasInvalidStoreAddress($data)) {
$this->addInvalidAddressAlert();
}
if ($this->hasInvalidStorePhone($data)) {
$this->addInvalidPhoneAlert();
}
if ($this->hasInvalidStoreName($data)) {
$this->addInvalidStoreNameAlert();
}
$this->setData('validation.store_info', false);
$data['active_tab'] = 'store_info';
return array();
}
$this->setData('validation.store_info', true);
$data['active_tab'] = 'campaign_defaults';
if ($this->hasValidMailChimpList()) {
$this->syncStore(array_merge($this->getOptions(), $data));
}
return $data;
}
/**
* @param $input
* @return array
*/
protected function compileStoreInfoData($input)
{
return array(
// store basics
'store_name' => trim((isset($input['store_name']) ? $input['store_name'] : get_option('blogname'))),
'store_street' => isset($input['store_street']) ? $input['store_street'] : false,
'store_city' => isset($input['store_city']) ? $input['store_city'] : false,
'store_state' => isset($input['store_state']) ? $input['store_state'] : false,
'store_postal_code' => isset($input['store_postal_code']) ? $input['store_postal_code'] : false,
'store_country' => isset($input['store_country']) ? $input['store_country'] : false,
'store_phone' => isset($input['store_phone']) ? $input['store_phone'] : false,
// locale info
'store_locale' => isset($input['store_locale']) ? $input['store_locale'] : false,
'store_timezone' => isset($input['store_timezone']) ? $input['store_timezone'] : false,
'store_currency_code' => isset($input['store_currency_code']) ? $input['store_currency_code'] : false,
'admin_email' => isset($input['admin_email']) && is_email($input['admin_email']) ? $input['admin_email'] : $this->getOption('admin_email', false),
);
}
/**
* @param array $data
* @return array|bool
*/
protected function hasInvalidStoreAddress($data)
{
$address_keys = array(
'admin_email',
'store_city',
'store_state',
'store_postal_code',
'store_country',
'store_street'
);
$invalid = array();
foreach ($address_keys as $address_key) {
if (empty($data[$address_key])) {
$invalid[] = $address_key;
}
}
return empty($invalid) ? false : $invalid;
}
/**
* @param $data
* @return bool
*/
protected function hasInvalidStorePhone($data)
{
if (empty($data['store_phone']) || strlen($data['store_phone']) <= 6) {
return true;
}
return false;
}
/**
* @param $data
* @return bool
*/
protected function hasInvalidStoreName($data)
{
if (empty($data['store_name'])) {
return true;
}
return false;
}
/**
*
*/
protected function addInvalidAddressAlert()
{
add_settings_error('mailchimp_store_settings', '', 'As part of the MailChimp Terms of Use, we require a contact email and a physical mailing address.');
}
/**
*
*/
protected function addInvalidPhoneAlert()
{
add_settings_error('mailchimp_store_settings', '', 'As part of the MailChimp Terms of Use, we require a valid phone number for your store.');
}
/**
*
*/
protected function addInvalidStoreNameAlert()
{
add_settings_error('mailchimp_store_settings', '', 'MailChimp for WooCommerce requires a Store Name to connect your store.');
}
/**
* STEP 3.
*
* Handle the 'campaign_defaults' tab post.
*
* @param $input
* @return array
*/
protected function validatePostCampaignDefaults($input)
{
$data = array(
'campaign_from_name' => isset($input['campaign_from_name']) ? $input['campaign_from_name'] : false,
'campaign_from_email' => isset($input['campaign_from_email']) && is_email($input['campaign_from_email']) ? $input['campaign_from_email'] : false,
'campaign_subject' => isset($input['campaign_subject']) ? $input['campaign_subject'] : get_option('blogname'),
'campaign_language' => isset($input['campaign_language']) ? $input['campaign_language'] : 'en',
'campaign_permission_reminder' => isset($input['campaign_permission_reminder']) ? $input['campaign_permission_reminder'] : 'You were subscribed to the newsletter from '.get_option('blogname'),
);
if (!$this->hasValidCampaignDefaults($data)) {
$this->setData('validation.campaign_defaults', false);
return array('active_tab' => 'campaign_defaults');
}
$this->setData('validation.campaign_defaults', true);
$data['active_tab'] = 'newsletter_settings';
return $data;
}
/**
* STEP 4.
*
* Handle the 'newsletter_settings' tab post.
*
* @param $input
* @return array
*/
protected function validatePostNewsletterSettings($input)
{
// default value.
$checkbox = $this->getOption('mailchimp_checkbox_defaults', 'check');
// see if it's posted in the form.
if (isset($input['mailchimp_checkbox_defaults']) && !empty($input['mailchimp_checkbox_defaults'])) {
$checkbox = $input['mailchimp_checkbox_defaults'];
}
$data = array(
'mailchimp_list' => isset($input['mailchimp_list']) ? $input['mailchimp_list'] : $this->getOption('mailchimp_list', ''),
'newsletter_label' => isset($input['newsletter_label']) ? $input['newsletter_label'] : $this->getOption('newsletter_label', 'Subscribe to our newsletter'),
'mailchimp_auto_subscribe' => isset($input['mailchimp_auto_subscribe']) ? (bool) $input['mailchimp_auto_subscribe'] : $this->getOption('mailchimp_auto_subscribe', '0'),
'mailchimp_checkbox_defaults' => $checkbox,
'mailchimp_checkbox_action' => isset($input['mailchimp_checkbox_action']) ? $input['mailchimp_checkbox_action'] : $this->getOption('mailchimp_checkbox_action', 'woocommerce_after_checkout_billing_form'),
'mailchimp_product_image_key' => isset($input['mailchimp_product_image_key']) ? $input['mailchimp_product_image_key'] : 'medium',
);
if ($data['mailchimp_list'] === 'create_new') {
$data['mailchimp_list'] = $this->createMailChimpList(array_merge($this->getOptions(), $data));
}
// as long as we have a list set, and it's currently in MC as a valid list, let's sync the store.
if (!empty($data['mailchimp_list']) && $this->api()->hasList($data['mailchimp_list'])) {
$this->setData('validation.newsletter_settings', true);
// sync the store with MC
$this->syncStore(array_merge($this->getOptions(), $data));
// start the sync automatically if the sync is false
if ((bool) $this->getData('sync.started_at', false) === false) {
$this->startSync();
$this->showSyncStartedMessage();
}
$data['active_tab'] = 'sync';
return $data;
}
$this->setData('validation.newsletter_settings', false);
$data['active_tab'] = 'newsletter_settings';
return $data;
}
/**
* @param null|array $data
* @return bool
*/
public function hasValidStoreInfo($data = null)
{
return $this->validateOptions(array(
'store_name', 'store_street', 'store_city', 'store_state',
'store_postal_code', 'store_country', 'store_phone',
'store_locale', 'store_timezone', 'store_currency_code',
'store_phone',
), $data);
}
/**
* @param null|array $data
* @return bool
*/
public function hasValidCampaignDefaults($data = null)
{
return $this->validateOptions(array(
'campaign_from_name', 'campaign_from_email', 'campaign_subject', 'campaign_language',
'campaign_permission_reminder'
), $data);
}
/**
* @param null|array $data
* @return bool
*/
public function hasValidApiKey($data = null)
{
if (!$this->validateOptions(array('mailchimp_api_key'), $data)) {
return false;
}
if (($pinged = $this->getCached('api-ping-check', null)) === null) {
if (($pinged = $this->api()->ping())) {
$this->setCached('api-ping-check', true, 120);
}
return $pinged;
}
return $pinged;
}
/**
* @return bool
*/
public function hasValidMailChimpList()
{
if (!$this->hasValidApiKey()) {
add_settings_error('mailchimp_api_key', '', 'You must supply your MailChimp API key to pull the lists.');
return false;
}
if (!($this->validateOptions(array('mailchimp_list')))) {
return $this->api()->getLists(true);
}
return $this->api()->hasList($this->getOption('mailchimp_list'));
}
/**
* @return array|bool|mixed|null
*/
public function getAccountDetails()
{
if (!$this->hasValidApiKey()) {
return false;
}
try {
if (($account = $this->getCached('api-account-name', null)) === null) {
if (($account = $this->api()->getProfile())) {
$this->setCached('api-account-name', $account, 120);
}
}
return $account;
} catch (\Exception $e) {
return false;
}
}
/**
* @return array|bool
*/
public function getMailChimpLists()
{
if (!$this->hasValidApiKey()) {
return false;
}
try {
if (($pinged = $this->getCached('api-lists', null)) === null) {
$pinged = $this->api()->getLists(true);
if ($pinged) {
$this->setCached('api-lists', $pinged, 120);
}
return $pinged;
}
return $pinged;
} catch (\Exception $e) {
return array();
}
}
/**
* @return array|bool
*/
public function getListName()
{
if (!$this->hasValidApiKey()) {
return false;
}
if (!($list_id = $this->getOption('mailchimp_list', false))) {
return false;
}
try {
if (($lists = $this->getCached('api-lists', null)) === null) {
$lists = $this->api()->getLists(true);
if ($lists) {
$this->setCached('api-lists', $lists, 120);
}
}
return array_key_exists($list_id, $lists) ? $lists[$list_id] : false;
} catch (\Exception $e) {
return array();
}
}
/**
* @return bool
*/
public function isReadyForSync()
{
if (!$this->hasValidApiKey()) {
return false;
}
if (!$this->getOption('mailchimp_list', false)) {
return false;
}
if (!$this->api()->hasList($this->getOption('mailchimp_list'))) {
return false;
}
if (!$this->api()->getStore($this->getUniqueStoreID())) {
return false;
}
return true;
}
/**
* @param null|array $data
* @return bool|string
*/
private function createMailChimpList($data = null)
{
if (empty($data)) {
$data = $this->getOptions();
}
$required = array(
'store_name', 'store_street', 'store_city', 'store_state',
'store_postal_code', 'store_country', 'campaign_from_name',
'campaign_from_email', 'campaign_subject', 'campaign_permission_reminder',
);
foreach ($required as $requirement) {
if (!isset($data[$requirement]) || empty($data[$requirement])) {
return false;
}
}
$submission = new MailChimp_WooCommerce_CreateListSubmission();
// allow the subscribers to choose preferred email type (html or text).
$submission->setEmailTypeOption(true);
// set the store name
$submission->setName($data['store_name']);
// set the campaign defaults
$submission->setCampaignDefaults(
$data['campaign_from_name'],
$data['campaign_from_email'],
$data['campaign_subject'],
$data['campaign_language']
);
// set the permission reminder message.
$submission->setPermissionReminder($data['campaign_permission_reminder']);
if (isset($data['admin_email']) && !empty($data['admin_email'])) {
$submission->setNotifyOnSubscribe($data['admin_email']);
$submission->setNotifyOnUnSubscribe($data['admin_email']);
}
$submission->setContact($this->address($data));
try {
$response = $this->api()->createList($submission);
$list_id = array_key_exists('id', $response) ? $response['id'] : false;
$this->setData('errors.mailchimp_list', false);
return $list_id;
} catch (MailChimp_WooCommerce_Error $e) {
$this->setData('errors.mailchimp_list', $e->getMessage());
return false;
}
}
/**
* @param null $data
* @return bool
*/
private function syncStore($data = null)
{
if (empty($data)) {
$data = $this->getOptions();
}
$list_id = $this->array_get($data, 'mailchimp_list', false);
$site_url = $this->getUniqueStoreID();
if (empty($list_id) || empty($site_url)) {
return false;
}
$new = false;
if (!($store = $this->api()->getStore($site_url))) {
$new = true;
$store = new MailChimp_WooCommerce_Store();
}
$call = $new ? 'addStore' : 'updateStore';
$time_key = $new ? 'store_created_at' : 'store_updated_at';
$store->setId($site_url);
$store->setPlatform('woocommerce');
// set the locale data
$store->setPrimaryLocale($this->array_get($data, 'store_locale', 'en'));
$store->setTimezone($this->array_get($data, 'store_timezone', 'America\New_York'));
$store->setCurrencyCode($this->array_get($data, 'store_currency_code', 'USD'));
// set the basics
$store->setName($this->array_get($data, 'store_name'));
$store->setDomain(get_option('siteurl'));
// don't know why we did this before
//$store->setEmailAddress($this->array_get($data, 'campaign_from_email'));
$store->setEmailAddress($this->array_get($data, 'admin_email'));
$store->setAddress($this->address($data));
$store->setPhone($this->array_get($data, 'store_phone'));
$store->setListId($list_id);
try {
// let's create a new store for this user through the API
$this->api()->$call($store);
// apply extra meta for store created at
$this->setData('errors.store_info', false);
$this->setData($time_key, time());
// on a new store push, we need to make sure we save the site script into a local variable.
if ($new) {
mailchimp_update_connected_site_script();
}
return true;
} catch (\Exception $e) {
$this->setData('errors.store_info', $e->getMessage());
}
return false;
}
/**
* @param array $data
* @return MailChimp_WooCommerce_Address
*/
private function address(array $data)
{
$address = new MailChimp_WooCommerce_Address();
if (isset($data['store_street']) && $data['store_street']) {
$address->setAddress1($data['store_street']);
}
if (isset($data['store_city']) && $data['store_city']) {
$address->setCity($data['store_city']);
}
if (isset($data['store_state']) && $data['store_state']) {
$address->setProvince($data['store_state']);
}
if (isset($data['store_country']) && $data['store_country']) {
$address->setCountry($data['store_country']);
}
if (isset($data['store_postal_code']) && $data['store_postal_code']) {
$address->setPostalCode($data['store_postal_code']);
}
if (isset($data['store_name']) && $data['store_name']) {
$address->setCompany($data['store_name']);
}
if (isset($data['store_phone']) && $data['store_phone']) {
$address->setPhone($data['store_phone']);
}
$address->setCountryCode($this->array_get($data, 'store_currency_code', 'USD'));
return $address;
}
/**
* @param array $required
* @param null $options
* @return bool
*/
private function validateOptions(array $required, $options = null)
{
$options = is_array($options) ? $options : $this->getOptions();
foreach ($required as $requirement) {
if (!isset($options[$requirement]) || empty($options[$requirement])) {
return false;
}
}
return true;
}
/**
* Start the sync
*/
private function startSync()
{
mailchimp_flush_sync_pointers();
$coupon_sync = new MailChimp_WooCommerce_Process_Coupons();
wp_queue($coupon_sync);
$job = new MailChimp_WooCommerce_Process_Products();
$job->flagStartSync();
wp_queue($job);
}
/**
* Show the sync started message right when they sync things.
*/
private function showSyncStartedMessage()
{
$text = 'Starting the sync process…<br/>'.
'<p id="sync-status-message">Please hang tight while we work our mojo. Sometimes the sync can take a while, '.
'especially on sites with lots of orders and/or products. You may refresh this page at '.
'anytime to check on the progress.</p>';
add_settings_error('mailchimp-woocommerce_notice', $this->plugin_name, __($text), 'updated');
}
}

View File

@@ -0,0 +1,4 @@
/**
* All of the CSS for your admin-specific functionality should be
* included in this file.
*/

View File

@@ -0,0 +1 @@
<?php // Silence is golden

View File

@@ -0,0 +1,32 @@
(function( $ ) {
'use strict';
/**
* All of the code for your admin-facing JavaScript source
* should reside in this file.
*
* Note: It has been assumed you will write jQuery code here, so the
* $ function reference has been prepared for usage within the scope
* of this function.
*
* This enables you to define handlers, for when the DOM is ready:
*
* $(function() {
*
* });
*
* When the window is loaded:
*
* $( window ).load(function() {
*
* });
*
* ...and/or other possibilities.
*
* Ideally, it is not considered best practise to attach more than a
* single DOM-ready or window-load handler for a particular page.
* Although scripts in the WordPress core, Plugins and Themes may be
* practising this, we should strive to set a better example in our own work.
*/
})( jQuery );

View File

@@ -0,0 +1,143 @@
<?php
$active_tab = isset($_GET['tab']) ? $_GET['tab'] : 'api_key';
$is_mailchimp_post = isset($_POST['mailchimp_woocommerce_settings_hidden']) && $_POST['mailchimp_woocommerce_settings_hidden'] === 'Y';
$handler = MailChimp_WooCommerce_Admin::connect();
//Grab all options for this particular tab we're viewing.
$options = get_option($this->plugin_name, array());
if (!isset($_GET['tab']) && isset($options['active_tab'])) {
$active_tab = $options['active_tab'];
}
$show_sync_tab = isset($_GET['resync']) ? $_GET['resync'] === '1' : false;;
$show_campaign_defaults = true;
$has_valid_api_key = false;
$allow_new_list = true;
$clicked_sync_button = $is_mailchimp_post&& $active_tab == 'sync';
if (isset($options['mailchimp_api_key']) && $handler->hasValidApiKey()) {
$has_valid_api_key = true;
// if we don't have a valid api key we need to redirect back to the 'api_key' tab.
if (($mailchimp_lists = $handler->getMailChimpLists()) && is_array($mailchimp_lists)) {
$show_campaign_defaults = false;
$allow_new_list = false;
}
// only display this button if the data is not syncing and we have a valid api key
if ((bool) $this->getData('sync.started_at', false)) {
$show_sync_tab = true;
}
}
?>
<style>
#sync-status-message strong {
font-weight:inherit;
}
#log-viewer {
background: #fff;
border: 1px solid #e5e5e5;
box-shadow: 0 1px 1px rgba(0,0,0,.04);
padding: 5px 20px;
}
#log-viewer-select {
padding: 10px 0 8px;
line-height: 28px;
}
#log-viewer pre {
font-family: monospace;
white-space: pre-wrap;
}
user agent stylesheet
pre, xmp, plaintext, listing {
display: block;
font-family: monospace;
white-space: pre;
margin: 1em 0px;
}
</style>
<?php if (!defined('PHP_VERSION_ID') || (PHP_VERSION_ID < 70000)): ?>
<div data-dismissible="notice-php-version" class="error notice notice-error is-dismissible">
<p><?php _e('MailChimp says: Please upgrade your PHP version to a minimum of 7.0', 'mailchimp-woocommerce'); ?></p>
</div>
<?php endif; ?>
<!-- Create a header in the default WordPress 'wrap' container -->
<div class="wrap">
<div id="icon-themes" class="icon32"></div>
<h2>MailChimp Settings</h2>
<h2 class="nav-tab-wrapper">
<a href="?page=mailchimp-woocommerce&tab=api_key" class="nav-tab <?php echo $active_tab == 'api_key' ? 'nav-tab-active' : ''; ?>">Connect</a>
<?php if($has_valid_api_key): ?>
<a href="?page=mailchimp-woocommerce&tab=store_info" class="nav-tab <?php echo $active_tab == 'store_info' ? 'nav-tab-active' : ''; ?>">Store Settings</a>
<?php if ($handler->hasValidStoreInfo()) : ?>
<?php if($show_campaign_defaults): ?>
<a href="?page=mailchimp-woocommerce&tab=campaign_defaults" class="nav-tab <?php echo $active_tab == 'campaign_defaults' ? 'nav-tab-active' : ''; ?>">List Defaults</a>
<?php endif; ?>
<a href="?page=mailchimp-woocommerce&tab=newsletter_settings" class="nav-tab <?php echo $active_tab == 'newsletter_settings' ? 'nav-tab-active' : ''; ?>">List Settings</a>
<?php if($show_sync_tab): ?>
<a href="?page=mailchimp-woocommerce&tab=sync" class="nav-tab <?php echo $active_tab == 'sync' ? 'nav-tab-active' : ''; ?>">Sync</a>
<a href="?page=mailchimp-woocommerce&tab=logs" class="nav-tab <?php echo $active_tab == 'logs' ? 'nav-tab-active' : ''; ?>">Logs</a>
<?php endif; ?>
<?php endif;?>
<?php endif; ?>
</h2>
<form method="post" name="cleanup_options" action="options.php">
<input type="hidden" name="mailchimp_woocommerce_settings_hidden" value="Y">
<?php
if (!$clicked_sync_button) {
settings_fields($this->plugin_name);
do_settings_sections($this->plugin_name);
include('tabs/notices.php');
}
?>
<input type="hidden" name="<?php echo $this->plugin_name; ?>[mailchimp_active_tab]" value="<?php echo esc_attr($active_tab); ?>"/>
<?php if ($active_tab == 'api_key' ): ?>
<?php include_once 'tabs/api_key.php'; ?>
<?php endif; ?>
<?php if ($active_tab == 'store_info' && $has_valid_api_key): ?>
<?php include_once 'tabs/store_info.php'; ?>
<?php endif; ?>
<?php if ($active_tab == 'campaign_defaults' ): ?>
<?php include_once 'tabs/campaign_defaults.php'; ?>
<?php endif; ?>
<?php if ($active_tab == 'newsletter_settings' ): ?>
<?php include_once 'tabs/newsletter_settings.php'; ?>
<?php endif; ?>
<?php if ($active_tab == 'sync' && $show_sync_tab): ?>
<?php include_once 'tabs/store_sync.php'; ?>
<?php endif; ?>
<?php if ($active_tab == 'logs' && $show_sync_tab): ?>
<?php include_once 'tabs/logs.php'; ?>
<?php endif; ?>
<?php if ($active_tab !== 'sync' && $active_tab !== 'logs') submit_button('Save all changes', 'primary','submit', TRUE); ?>
</form>
<?php if ($active_tab == 'sync'): ?>
<h2 style="padding-top: 1em;">More Information</h2>
<ul>
<li>Have a larger store or having issues syncing? Consider using <a href="https://github.com/mailchimp/mc-woocommerce/issues/158" target="_blank">WP-CLI</a>.</li>
<li>Order and customer information will not sync if they contain an Amazon or generic email address.</li>
<li>Need help to connect your store? Visit the MailChimp <a href="http://kb.mailchimp.com/integrations/e-commerce/connect-or-disconnect-mailchimp-for-woocommerce/" target="_blank">Knowledge Base</a>.</li>
<li>Want to tell us how we're doing? <a href="https://wordpress.org/support/plugin/mailchimp-for-woocommerce/reviews/" target="_blank">Leave a review on Wordpress.org</a>.</li>
</ul>
<?php endif; ?>
</div><!-- /.wrap -->

View File

@@ -0,0 +1,25 @@
<?php
if (isset($options['mailchimp_api_key']) && !$handler->hasValidApiKey()) {
include_once __DIR__.'/errors/missing_api_key.php';
}
?>
<input type="hidden" name="mailchimp_active_settings_tab" value="api_key"/>
<h2 style="padding-top: 1em;">API Information</h2>
<p>To find your MailChimp API key, log into your account settings > Extras > API keys. From there, either grab an existing key or generate a new one for your WooCommerce store. </p>
<!-- remove some meta and generators from the <head> -->
<fieldset>
<legend class="screen-reader-text">
<span>MailChimp API Key</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-mailchimp-api-key">
<input style="width: 30%;" type="password" id="<?php echo $this->plugin_name; ?>-mailchimp-api-key" name="<?php echo $this->plugin_name; ?>[mailchimp_api_key]" value="<?php echo isset($options['mailchimp_api_key']) ? $options['mailchimp_api_key'] : '' ?>" />
<span><?php esc_attr_e('Enter your MailChimp API key.', $this->plugin_name); ?></span>
</label>
</fieldset>

View File

@@ -0,0 +1,74 @@
<?php
$handler = MailChimp_WooCommerce_Admin::connect();
// if we don't have valid campaign defaults we need to redirect back to the 'campaign_defaults' tab.
if (!$handler->hasValidApiKey()) {
wp_redirect('options-general.php?page=mailchimp-woocommerce&tab=api_key&error_notice=missing_api_key');
}
if (!$handler->hasValidStoreInfo()) {
wp_redirect('options-general.php?page=mailchimp-woocommerce&tab=store_info&error_notice=missing_store');
}
?>
<input type="hidden" name="mailchimp_active_settings_tab" value="campaign_defaults"/>
<h2 style="padding-top: 1em;">List Defaults</h2>
<p>Please fill out the default campaign information.</p>
<fieldset>
<legend class="screen-reader-text">
<span>Contact Name</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-campaign-from-name-label">
<input style="width: 30%;" type="text" id="<?php echo $this->plugin_name; ?>-campaign-from-name-label" name="<?php echo $this->plugin_name; ?>[campaign_from_name]" value="<?php echo isset($options['campaign_from_name']) ? $options['campaign_from_name'] : '' ?>" />
<span><?php esc_attr_e('Default from name', $this->plugin_name); ?></span>
</label>
</fieldset>
<fieldset>
<legend class="screen-reader-text">
<span>From Email</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-campaign-from-email-label">
<input style="width: 30%;" type="text" id="<?php echo $this->plugin_name; ?>-campaign-from-email-label" name="<?php echo $this->plugin_name; ?>[campaign_from_email]" value="<?php echo isset($options['campaign_from_email']) ? $options['campaign_from_email'] : get_option('admin_email') ?>" />
<span><?php esc_attr_e('Default from email', $this->plugin_name); ?></span>
</label>
</fieldset>
<fieldset>
<legend class="screen-reader-text">
<span>Default Subject</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-campaign-subject-label">
<input style="width: 30%;" type="text" id="<?php echo $this->plugin_name; ?>-campaign-subject-label" name="<?php echo $this->plugin_name; ?>[campaign_subject]" value="<?php echo isset($options['campaign_subject']) ? $options['campaign_subject'] : get_option('blogname') ?>" />
<span><?php esc_attr_e('Default subject', $this->plugin_name); ?></span>
</label>
</fieldset>
<fieldset>
<legend class="screen-reader-text">
<span>Default Language</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-campaign-language-label">
<select id="<?php echo $this->plugin_name; ?>-campaign-language-label" name="<?php echo $this->plugin_name; ?>[campaign_language]" style="width:30%" required>
<?php $selected_locale = isset($options['campaign_language']) && !empty($options['campaign_language']) ? $options['campaign_language'] : 'en'; ?>
<?php
foreach(MailChimp_Api_Locales::simple() as $locale_key => $local_value) {
echo '<option value="' . esc_attr( $locale_key ) . '" ' . selected($locale_key === $selected_locale, true, false ) . '>' . esc_html( $local_value ) . '</option>';
}
?>
</select>
<span><?php esc_attr_e('Default language', $this->plugin_name); ?></span>
</label>
</fieldset>
<fieldset>
<legend class="screen-reader-text">
<span>Permission Reminder</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-campaign-permission-reminder-label">
<textarea style="width: 30%;" id="<?php echo $this->plugin_name; ?>-campaign-permission-reminder-label" name="<?php echo $this->plugin_name; ?>[campaign_permission_reminder]"><?php echo isset($options['campaign_permission_reminder']) ? $options['campaign_permission_reminder'] : 'You were subscribed to the newsletter from '.get_option('blogname') ?></textarea>
<span><?php esc_attr_e('Permission reminder message', $this->plugin_name); ?></span>
</label>
</fieldset>

View File

@@ -0,0 +1,81 @@
<?php
if (!empty( $_REQUEST['handle'])) {
if (!empty($_REQUEST['_wpnonce']) && wp_verify_nonce($_REQUEST['_wpnonce'], 'remove_log')) {
$log_handler = new WC_Log_Handler_File();
$log_handler->remove($_REQUEST['handle']);
wp_redirect('options-general.php?page=mailchimp-woocommerce&tab=logs');
}
}
$files = defined('WC_LOG_DIR') ? @scandir( WC_LOG_DIR ) : array();
$logs = array();
if (!empty($files)) {
foreach ($files as $key => $value) {
if (!in_array( $value, array( '.', '..' ))) {
if (!is_dir($value) && mailchimp_string_contains($value, 'mailchimp_woocommerce')) {
$logs[sanitize_title($value)] = $value;
}
}
}
}
if (!empty($_REQUEST['log_file']) && isset($logs[sanitize_title( $_REQUEST['log_file'])])) {
$viewed_log = $logs[sanitize_title($_REQUEST['log_file'])];
} elseif (!empty($logs)) {
$viewed_log = current( $logs );
}
$handle = !empty($viewed_log) ? substr($viewed_log, 0, strlen($viewed_log) > 37 ? strlen($viewed_log) - 37 : strlen($viewed_log) - 4) : '';
?>
<h2 style="padding-top: 1em;">Logging Preference</h2>
<p>
Advanced troubleshooting can be conducted with the logging capability turned on.
By default, its set to “none” and you may toggle to either “standard” or “debug” as needed.
With standard logging, you can see basic information about the data submission to MailChimp including any errors.
“Debug” gives a much deeper insight that is useful to share with support if problems arise.
</p>
<fieldset>
<legend class="screen-reader-text">
<span>Logging Preference</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-logging">
<select name="<?php echo $this->plugin_name; ?>[mailchimp_logging]" style="width:30%" required>
<?php $logging_preference = mailchimp_environment_variables()->logging; ?>
<?php
foreach(array('none' => 'None', 'debug' => 'Debug', 'standard' => 'Standard',) as $log_value => $log_label) {
echo '<option value="'.esc_attr($log_value).'" '.selected($log_value === $logging_preference, true, false ) . '>' . esc_html($log_label) . '</option>';
}
?>
</select>
</label>
</fieldset>
<?php submit_button('Save all changes', 'primary','submit', TRUE);?>
<?php if (isset($logs) && isset($viewed_log)) : ?>
<div id="log-viewer-select">
<div class="alignleft">
<h2>
<?php echo esc_html( $viewed_log ); ?>
<?php if ( ! empty( $handle ) ) : ?>
<a class="page-title-action" href="<?php echo esc_url( wp_nonce_url( add_query_arg( array( 'handle' => $handle ), admin_url( 'options-general.php?page=mailchimp-woocommerce&tab=logs&mc_action=remove_log' ) ), 'remove_log' ) ); ?>" class="button"><?php esc_html_e( 'Delete log', 'woocommerce' );?></a>
<?php endif; ?>
</h2>
</div>
<div class="alignright">
<form action="<?php echo admin_url( 'options-general.php?page=mailchimp-woocommerce&tab=logs&mc_action=view_log' ); ?>" method="post">
<input type="hidden" name="<?php echo $this->plugin_name; ?>[mailchimp_active_tab]" value="logs"/>
<select name="log_file">
<?php foreach ( $logs as $log_key => $log_file ) : ?>
<option value="<?php echo esc_attr( $log_key ); ?>" <?php selected( sanitize_title( $viewed_log ), $log_key ); ?>><?php echo esc_html( $log_file ); ?> (<?php echo date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), filemtime( WC_LOG_DIR . $log_file ) ); ?>)</option>
<?php endforeach; ?>
</select>
<input type="submit" class="button" value="<?php esc_attr_e( 'View', 'woocommerce' ); ?>" />
</form>
</div>
<div class="clear"></div>
</div>
<div id="log-viewer">
<pre><?php echo esc_html( file_get_contents( WC_LOG_DIR . $viewed_log ) ); ?></pre>
</div>
<?php else : ?>
<div class="updated woocommerce-message inline"><p><?php _e( 'There are currently no logs to view.', 'woocommerce' ); ?></p></div>
<?php endif; ?>

View File

@@ -0,0 +1,149 @@
<?php
// if we don't have valid campaign defaults we need to redirect back to the 'campaign_defaults' tab.
if (!$handler->hasValidApiKey()) {
wp_redirect('options-general.php?page=mailchimp-woocommerce&tab=api_key&error_notice=missing_api_key');
}
// if we don't have valid store information, we need to redirect back to the 'store_info' tab.
if (!$handler->hasValidStoreInfo()) {
wp_redirect('options-general.php?page=mailchimp-woocommerce&tab=store_info&error_notice=missing_store');
}
// if we don't have a valid api key we need to redirect back to the 'api_key' tab.
if (!isset($mailchimp_lists) && ($mailchimp_lists = $handler->getMailChimpLists()) === false) {
wp_redirect('options-general.php?page=mailchimp-woocommerce&tab=api_key&error_notice=missing_api_key');
}
// if we don't have valid campaign defaults we need to redirect back to the 'campaign_defaults' tab.
if (empty($mailchimp_lists) && !$handler->hasValidCampaignDefaults()) {
wp_redirect('options-general.php?page=mailchimp-woocommerce&tab=campaign_defaults&error_notice=missing_campaign_defaults');
}
$list_is_configured = isset($options['mailchimp_list']) && (!empty($options['mailchimp_list'])) && array_key_exists($options['mailchimp_list'], $mailchimp_lists);
?>
<?php if(($newsletter_settings_error = $this->getData('errors.mailchimp_list', false))) : ?>
<div class="error notice is-dismissable">
<p><?php _e($newsletter_settings_error, 'mailchimp-woocommerce'); ?></p>
</div>
<?php endif; ?>
<input type="hidden" name="mailchimp_active_settings_tab" value="newsletter_settings"/>
<h2 style="padding-top: 1em;">List Settings</h2>
<p>Please apply your list settings. If you don't have a list, you can choose to create one.</p>
<fieldset>
<legend class="screen-reader-text">
<span>List Name</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-mailchimp-list-label">
<select name="<?php echo $this->plugin_name; ?>[mailchimp_list]" style="width:30%" required <?php if($list_is_configured): ?> disabled <?php endif; ?>>
<?php if(!isset($allow_new_list) || $allow_new_list === true): ?>
<option value="create_new">Create New List</option>
<?php endif ?>
<?php if(isset($allow_new_list) && $allow_new_list === false): ?>
<option value="">-- Select List --</option>
<?php endif; ?>
<?php
if (is_array($mailchimp_lists)) {
$selected_list = isset($options['mailchimp_list']) ? $options['mailchimp_list'] : null;
foreach ($mailchimp_lists as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '" ' . selected(((string) $key === (string) $selected_list), true, false) . '>' . esc_html( $value ) . '</option>';
}
}
?>
</select>
<span><?php esc_attr_e('Choose a list to sync with your store.', $this->plugin_name); ?></span>
</label>
</fieldset>
<fieldset>
<legend class="screen-reader-text">
<span>Auto Subscribe On Initial Sync</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-mailchimp-auto-subscribe">
<select name="<?php echo $this->plugin_name; ?>[mailchimp_auto_subscribe]" style="width:30%" required <?php if($list_is_configured): ?> disabled <?php endif; ?>>
<?php
$enable_auto_subscribe = (array_key_exists('mailchimp_auto_subscribe', $options) && !is_null($options['mailchimp_auto_subscribe'])) ? $options['mailchimp_auto_subscribe'] : '1';
foreach (array('0' => 'No', '1' => 'Yes') as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '" ' . selected($key == $enable_auto_subscribe, true, false ) . '>' . esc_html( $value ) . '</option>';
}
?>
</select>
<span><?php esc_attr_e('During initial sync, auto subscribe the existing customers.', $this->plugin_name); ?></span>
</label>
</fieldset>
<h2 style="padding-top: 1em;">Opt-in Settings</h2>
<p>Add text to go along with the opt-in checkbox, and choose a default display option. Customers can click a box at checkout to opt in to your newsletter. Write a signup message and choose how you want this checkbox to appear. </p>
<fieldset>
<legend class="screen-reader-text">
<span>Newsletter Label</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-newsletter-checkbox-label">
<input style="width: 30%;" type="text" id="<?php echo $this->plugin_name; ?>-newsletter-checkbox-label" name="<?php echo $this->plugin_name; ?>[newsletter_label]" value="<?php echo isset($options['newsletter_label']) ? $options['newsletter_label'] : 'Subscribe to our newsletter' ?>" />
<span><?php esc_attr_e('Enter text for the opt-in checkbox', $this->plugin_name); ?></span>
</label>
</fieldset>
<h4 style="padding-top: 1em;font-weight:normal;">Checkbox Display Options</h4>
<fieldset>
<legend class="screen-reader-text">
<span>Checkbox Display Options</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-newsletter-checkbox-defaults">
<?php $checkbox_default_settings = (array_key_exists('mailchimp_checkbox_defaults', $options) && !is_null($options['mailchimp_checkbox_defaults'])) ? $options['mailchimp_checkbox_defaults'] : 'check'; ?>
<input type="radio" name="<?php echo $this->plugin_name; ?>[mailchimp_checkbox_defaults]" value="check"<?php if($checkbox_default_settings === 'check') echo ' checked="checked" '; ?>>Visible, checked by default<br>
<input type="radio" name="<?php echo $this->plugin_name; ?>[mailchimp_checkbox_defaults]" value="uncheck"<?php if($checkbox_default_settings === 'uncheck') echo ' checked="checked" '; ?>>Visible, unchecked by default<br/>
<input type="radio" name="<?php echo $this->plugin_name; ?>[mailchimp_checkbox_defaults]" value="hide"<?php if($checkbox_default_settings === 'hide') echo ' checked="checked" '; ?>>Hidden, unchecked by default<br/>
</label>
</fieldset>
<h4 style="padding-top: 1em;font-weight:normal;">Advanced Checkbox Settings</h4>
<p>
To change the location of the opt-in checkbox at checkout, input one of the
<a href="https://docs.woocommerce.com/wc-apidocs/hook-docs.html" target="_blank">
available WooCommerce form actions.
</a>
</p>
<fieldset>
<legend class="screen-reader-text">
<span>Newsletter Checkbox Action</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-newsletter-checkbox-action">
<input style="width: 30%;" type="text" id="<?php echo $this->plugin_name; ?>-newsletter-checkbox-action" name="<?php echo $this->plugin_name; ?>[mailchimp_checkbox_action]" value="<?php echo isset($options['mailchimp_checkbox_action']) ? $options['mailchimp_checkbox_action'] : 'woocommerce_after_checkout_billing_form' ?>" />
<span><?php esc_attr_e('Enter a WooCommerce form action', $this->plugin_name); ?></span>
</label>
</fieldset>
<h2 style="padding-top: 1em;">Product Image Size</h2>
<p>Define the product image size used by abandoned carts, order notifications, and product recommendations.</p>
<fieldset>
<legend class="screen-reader-text">
<span>Product Image Size</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-mailchimp-product_image_key">
<select name="<?php echo $this->plugin_name; ?>[mailchimp_product_image_key]" style="width:30%">
<?php
$enable_auto_subscribe = (array_key_exists('mailchimp_product_image_key', $options) && !is_null($options['mailchimp_product_image_key'])) ? $options['mailchimp_product_image_key'] : 'medium';
foreach (mailchimp_woocommerce_get_all_image_sizes_list() as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '" ' . selected($key == $enable_auto_subscribe, true, false ) . '>' . esc_html( $value ) . '</option>';
}
?>
</select>
<span><?php esc_attr_e('Select an image size', $this->plugin_name); ?></span>
</label>
</fieldset>

View File

@@ -0,0 +1,39 @@
<?php if(isset($_GET['error_notice'])): ?>
<div class="error notice is-dismissable">
<?php
switch($_GET['error_notice']) {
case 'missing_api_key':
_e('MailChimp says: You must enter in a valid API key.', 'mailchimp-woocommerce');
break;
case 'missing_campaign_defaults':
_e('MailChimp says: Sorry you must set up your campaign defaults before you proceed!', 'mailchimp-woocommerce');
break;
case 'missing_list':
_e('MailChimp says: You must select a marketing list.', 'mailchimp-woocommerce');
break;
case 'missing_store':
_e('MailChimp says: Sorry you must set up your store before you proceed!', 'mailchimp-woocommerce');
break;
case 'not_ready_for_sync':
_e('MailChimp says: You are not fully ready to run the Store Sync, please verify your settings before proceeding.', 'mailchimp-woocommerce');
break;
default:
}
?>
</div>
<?php endif; ?>
<?php if (isset($_GET['success_notice'])): ?>
<div class="success notice is-dismissable">
<?php
switch($_GET['error_notice']) {
case 're-sync-started':
_e('MailChimp says: Your re-sync has been started!', 'mailchimp-woocommerce');
break;
default:
}
?>
</div>
<?php endif; ?>

View File

@@ -0,0 +1,215 @@
<?php
$handler = MailChimp_WooCommerce_Admin::connect();
// if we don't have valid campaign defaults we need to redirect back to the 'campaign_defaults' tab.
if (!$handler->hasValidApiKey()) {
wp_redirect('options-general.php?page=mailchimp-woocommerce&tab=api_key&error_notice=missing_api_key');
}
?>
<input type="hidden" name="mailchimp_active_settings_tab" value="store_info"/>
<h2 style="padding-top: 1em;">Store Settings</h2>
<p>Please provide the following information about your WooCommerce store.</p>
<fieldset>
<legend class="screen-reader-text">
<span>Store Name</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-store-name-label">
<input required style="width: 30%;" type="text" id="<?php echo $this->plugin_name; ?>-store-name-label" name="<?php echo $this->plugin_name; ?>[store_name]" value="<?php echo isset($options['store_name']) ? $options['store_name'] : get_option('blogname') ?>" />
<span>
<?php
if (!empty($options['store_name']) ) {
esc_attr_e('Name', $this->plugin_name);
} else {
esc_attr_e('Name', $this->plugin_name); echo '<span style="color:red;">*</span>';
}
?>
</span>
</label>
</fieldset>
<fieldset>
<legend class="screen-reader-text">
<span>Email</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-admin-email-label">
<input required style="width: 30%;" type="email" id="<?php echo $this->plugin_name; ?>-admin-email-label" name="<?php echo $this->plugin_name; ?>[admin_email]" value="<?php echo isset($options['admin_email']) ? $options['admin_email'] : get_option('admin_email') ?>" />
<span>
<?php
if (!empty($options['admin_email']) ) {
esc_attr_e('Email', $this->plugin_name);
} else {
esc_attr_e('Email', $this->plugin_name); echo '<span style="color:red;">*</span>';
}
?>
</span>
</label>
</fieldset>
<fieldset>
<legend class="screen-reader-text">
<span>Street Address</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-store-address-label">
<input required style="width: 30%;" type="text" id="<?php echo $this->plugin_name; ?>-store-address-label" name="<?php echo $this->plugin_name; ?>[store_street]" value="<?php echo isset($options['store_street']) ? $options['store_street'] : '' ?>" />
<span>
<?php
if (!empty($options['store_street']) ) {
esc_attr_e('Street address', $this->plugin_name);
} else {
esc_attr_e('Street address', $this->plugin_name); echo '<span style="color:red;">*</span>';
}
?>
</span>
</label>
</fieldset>
<fieldset>
<legend class="screen-reader-text">
<span>City</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-store-city-label">
<input required style="width: 30%;" type="text" id="<?php echo $this->plugin_name; ?>-store-city-label" name="<?php echo $this->plugin_name; ?>[store_city]" value="<?php echo isset($options['store_city']) ? $options['store_city'] : '' ?>" />
<span>
<?php
if (!empty($options['store_city']) ) {
esc_attr_e('City', $this->plugin_name);
} else {
esc_attr_e('City', $this->plugin_name); echo '<span style="color:red;">*</span>';
}
?>
</span>
</label>
</fieldset>
<fieldset>
<legend class="screen-reader-text">
<span>State</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-store-state-label">
<input required style="width: 30%;" type="text" id="<?php echo $this->plugin_name; ?>-store-state-label" name="<?php echo $this->plugin_name; ?>[store_state]" value="<?php echo isset($options['store_state']) ? $options['store_state'] : '' ?>" />
<span>
<?php
if (!empty($options['store_state']) ) {
esc_attr_e('State', $this->plugin_name);
} else {
esc_attr_e('State', $this->plugin_name); echo '<span style="color:red;">*</span>';
}
?>
</span>
</label>
</fieldset>
<fieldset>
<legend class="screen-reader-text">
<span>Postal Code</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-store-state-label">
<input required style="width: 30%;" type="text" id="<?php echo $this->plugin_name; ?>-store-postal-code-label" name="<?php echo $this->plugin_name; ?>[store_postal_code]" value="<?php echo isset($options['store_postal_code']) ? $options['store_postal_code'] : '' ?>" />
<span>
<?php
if (!empty($options['store_postal_code']) ) {
esc_attr_e('Postal Code', $this->plugin_name);
} else {
esc_attr_e('Postal Code', $this->plugin_name); echo '<span style="color:red;">*</span>';
}
?>
</span>
</label>
</fieldset>
<fieldset>
<legend class="screen-reader-text">
<span>Country</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-store-country-label">
<input required style="width: 30%;" type="text" id="<?php echo $this->plugin_name; ?>-store-country-label" name="<?php echo $this->plugin_name; ?>[store_country]" value="<?php echo isset($options['store_country']) ? $options['store_country'] : 'US' ?>" />
<span>
<?php
if (!empty($options['store_country'])) {
esc_attr_e('Country', $this->plugin_name);
} else {
esc_attr_e('Country', $this->plugin_name); echo '<span style="color:red;">*</span>';
}
?>
</span>
</label>
</fieldset>
<fieldset>
<legend class="screen-reader-text">
<span>Phone</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-store-phone-label">
<input required style="width: 30%;" type="text" id="<?php echo $this->plugin_name; ?>-store-phone-label" name="<?php echo $this->plugin_name; ?>[store_phone]" value="<?php echo isset($options['store_phone']) ? $options['store_phone'] : '' ?>" />
<span>
<?php
if (!empty($options['store_phone']) ) {
esc_attr_e('Phone Number', $this->plugin_name);
} else {
esc_attr_e('Phone Number', $this->plugin_name); echo '<span style="color:red;">*</span>';
}
?>
</span>
</label>
</fieldset>
<h2 style="padding-top: 1em;">Locale Settings</h2>
<p>Please apply your locale settings. If you're unsure about these, use the defaults.</p>
<fieldset>
<legend class="screen-reader-text">
<span>Locale</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-store-locale-label">
<select name="<?php echo $this->plugin_name; ?>[store_locale]" style="width:30%" required>
<?php $selected_locale = isset($options['store_locale']) && !empty($options['store_locale']) ? $options['store_locale'] : 'en'; ?>
<?php
foreach(MailChimp_Api_Locales::simple() as $locale_key => $local_value) {
echo '<option value="' . esc_attr( $locale_key ) . '" ' . selected($locale_key === $selected_locale, true, false ) . '>' . esc_html( $local_value ) . '</option>';
}
?>
</select>
<span><?php esc_attr_e('Locale', $this->plugin_name); ?></span>
</label>
</fieldset>
<fieldset>
<legend class="screen-reader-text">
<span>Currency Code</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-store-currency-code-label">
<select name="<?php echo $this->plugin_name; ?>[store_currency_code]" style="width:30%" required>
<?php
$selected_currency_code = isset($options['store_currency_code']) && !empty($options['store_currency_code']) ? $options['store_currency_code'] : 'USD';
foreach (MailChimp_WooCommerce_CurrencyCodes::lists() as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '" ' . selected($key === $selected_currency_code, true, false ) . '>' . esc_html( $value ) . '</option>';
}
?>
</select>
<span><?php esc_attr_e('Currency', $this->plugin_name); ?></span>
</label>
</fieldset>
<fieldset>
<legend class="screen-reader-text">
<span>Timezone</span>
</legend>
<label for="<?php echo $this->plugin_name; ?>-store-timezone-label">
<select name="<?php echo $this->plugin_name; ?>[store_timezone]" style="width:30%" required>
<?php $selected_timezone = isset($options['store_timezone']) && !empty($options['store_timezone']) ? $options['store_timezone'] : 'America/New_York'; ?>
<?php
foreach(mailchimp_get_timezone_list() as $t) {
echo '<option value="' . esc_attr( $t['zone'] ) . '" ' . selected($t['zone'] === $selected_timezone, true, false ) . '>' . esc_html( $t['diff_from_GMT'] . ' - ' . $t['zone'] ) . '</option>';
}
?>
</select>
<span><?php esc_attr_e('Timezone', $this->plugin_name); ?></span>
</label>
</fieldset>

View File

@@ -0,0 +1,73 @@
<?php
$mailchimp_total_products = $mailchimp_total_orders = 0;
$store_id = mailchimp_get_store_id();
$product_count = mailchimp_get_product_count();
$order_count = mailchimp_get_order_count();
$store_syncing = false;
$last_updated_time = get_option('mailchimp-woocommerce-resource-last-updated');
$sync_started_at = get_option('mailchimp-woocommerce-sync.started_at');
if (!empty($sync_started_at)) {
$sync_started_at = mailchimp_date_local($sync_started_at);
} else {
$sync_started_at = new \DateTime();
}
$sync_completed_at = get_option('mailchimp-woocommerce-sync.completed_at');
if (!empty($sync_completed_at)) {
$sync_completed_at = mailchimp_date_local($sync_completed_at);
} else {
$sync_completed_at = false;
}
$account_name = 'n/a';
$mailchimp_list_name = 'n/a';
if (!empty($last_updated_time)) {
$last_updated_time = mailchimp_date_local($last_updated_time);
}
if (($mailchimp_api = mailchimp_get_api()) && ($store = $mailchimp_api->getStore($store_id))) {
$store_syncing = $store->isSyncing();
if (($account_details = $handler->getAccountDetails())) {
$account_name = $account_details['account_name'];
}
try {
$products = $mailchimp_api->products($store_id, 1, 1);
$mailchimp_total_products = $products['total_items'];
if ($mailchimp_total_products > $product_count) $mailchimp_total_products = $product_count;
} catch (\Exception $e) { $mailchimp_total_products = 0; }
try {
$orders = $mailchimp_api->orders($store_id, 1, 1);
$mailchimp_total_orders = $orders['total_items'];
if ($mailchimp_total_orders > $order_count) $mailchimp_total_orders = $order_count;
} catch (\Exception $e) { $mailchimp_total_orders = 0; }
$mailchimp_list_name = $handler->getListName();
}
?>
<input type="hidden" name="mailchimp_active_settings_tab" value="store_sync"/>
<h2 style="padding-top: 1em;">Sync Information</h2>
<?php if ($sync_started_at): ?>
<p><strong>Started:</strong> <i><?php echo $sync_started_at->format('D, M j, Y g:i A'); ?></i></p>
<?php endif; ?>
<?php if ($sync_completed_at): ?>
<p><strong>Finished:</strong> <i><?php echo $sync_completed_at->format('D, M j, Y g:i A'); ?></i></p>
<?php endif; ?>
<?php if ($last_updated_time): ?>
<p><strong>Last Updated:</strong> <i><?php echo $last_updated_time->format('D, M j, Y g:i A'); ?></i></p>
<?php endif; ?>
<p><strong>Account Connected:</strong> <?php echo $account_name; ?></p>
<p><strong>List Connected:</strong> <?php echo $mailchimp_list_name; ?></p>
<p><strong>Products Synced:</strong> <?php echo $mailchimp_total_products; ?></p>
<p><strong>Orders Synced:</strong> <?php echo $mailchimp_total_orders; ?></p>
<?php if($mailchimp_api && (!$store_syncing || isset($_GET['resync']) && $_GET['resync'] === '1')): ?>
<h2 style="padding-top: 1em;">Advanced</h2>
<p>
You can resync your list at any time without losing any of your e-commerce data.
</p>
<?php submit_button('Resync', 'primary','submit', TRUE); ?>
<?php endif; ?>

View File

@@ -0,0 +1,668 @@
<?php
// If this file is called directly, abort.
if (!defined( 'WPINC')) {
die;
}
$mailchimp_woocommerce_spl_autoloader = true;
spl_autoload_register(function($class) {
$classes = array(
// includes root
'MailChimp_Service' => 'includes/class-mailchimp-woocommerce-service.php',
'MailChimp_WooCommerce_Options' => 'includes/class-mailchimp-woocommerce-options.php',
'MailChimp_Newsletter' => 'includes/class-mailchimp-woocommerce-newsletter.php',
'MailChimp_WooCommerce_Loader' => 'includes/class-mailchimp-woocommerce-loader.php',
'MailChimp_WooCommerce_i18n' => 'includes/class-mailchimp-woocommerce-i18n.php',
'MailChimp_WooCommerce_Deactivator' => 'includes/class-mailchimp-woocommerce-deactivator.php',
'MailChimp_WooCommerce_Activator' => 'includes/class-mailchimp-woocommerce-activator.php',
'MailChimp_WooCommerce' => 'includes/class-mailchimp-woocommerce.php',
// includes/api/assets
'MailChimp_WooCommerce_Address' => 'includes/api/assets/class-mailchimp-address.php',
'MailChimp_WooCommerce_Cart' => 'includes/api/assets/class-mailchimp-cart.php',
'MailChimp_WooCommerce_Customer' => 'includes/api/assets/class-mailchimp-customer.php',
'MailChimp_WooCommerce_LineItem' => 'includes/api/assets/class-mailchimp-line-item.php',
'MailChimp_WooCommerce_Order' => 'includes/api/assets/class-mailchimp-order.php',
'MailChimp_WooCommerce_Product' => 'includes/api/assets/class-mailchimp-product.php',
'MailChimp_WooCommerce_ProductVariation' => 'includes/api/assets/class-mailchimp-product-variation.php',
'MailChimp_WooCommerce_PromoCode' => 'includes/api/assets/class-mailchimp-promo-code.php',
'MailChimp_WooCommerce_PromoRule' => 'includes/api/assets/class-mailchimp-promo-rule.php',
'MailChimp_WooCommerce_Store' => 'includes/api/assets/class-mailchimp-store.php',
// includes/api/errors
'MailChimp_WooCommerce_Error' => 'includes/api/errors/class-mailchimp-error.php',
'MailChimp_WooCommerce_ServerError' => 'includes/api/errors/class-mailchimp-server-error.php',
// includes/api/helpers
'MailChimp_WooCommerce_CurrencyCodes' => 'includes/api/helpers/class-mailchimp-woocommerce-api-currency-codes.php',
'MailChimp_Api_Locales' => 'includes/api/helpers/class-mailchimp-woocommerce-api-locales.php',
// includes/api
'MailChimp_WooCommerce_MailChimpApi' => 'includes/api/class-mailchimp-api.php',
'MailChimp_WooCommerce_Api' => 'includes/api/class-mailchimp-woocommerce-api.php',
'MailChimp_WooCommerce_CreateListSubmission' => 'includes/api/class-mailchimp-woocommerce-create-list-submission.php',
'MailChimp_WooCommerce_Transform_Coupons' => 'includes/api/class-mailchimp-woocommerce-transform-coupons.php',
'MailChimp_WooCommerce_Transform_Orders' => 'includes/api/class-mailchimp-woocommerce-transform-orders-wc3.php',
'MailChimp_WooCommerce_Transform_Products' => 'includes/api/class-mailchimp-woocommerce-transform-products.php',
// includes/processes
'MailChimp_WooCommerce_Abstract_Sync' => 'includes/processes/class-mailchimp-woocommerce-abstract-sync.php',
'MailChimp_WooCommerce_Cart_Update' => 'includes/processes/class-mailchimp-woocommerce-cart-update.php',
'MailChimp_WooCommerce_Process_Coupons' => 'includes/processes/class-mailchimp-woocommerce-process-coupons.php',
'MailChimp_WooCommerce_Process_Orders' => 'includes/processes/class-mailchimp-woocommerce-process-orders.php',
'MailChimp_WooCommerce_Process_Products' => 'includes/processes/class-mailchimp-woocommerce-process-products.php',
'MailChimp_WooCommerce_SingleCoupon' => 'includes/processes/class-mailchimp-woocommerce-single-coupon.php',
'MailChimp_WooCommerce_Single_Order' => 'includes/processes/class-mailchimp-woocommerce-single-order.php',
'MailChimp_WooCommerce_Single_Product' => 'includes/processes/class-mailchimp-woocommerce-single-product.php',
'MailChimp_WooCommerce_User_Submit' => 'includes/processes/class-mailchimp-woocommerce-user-submit.php',
'MailChimp_WooCommerce_Public' => 'public/class-mailchimp-woocommerce-public.php',
'MailChimp_WooCommerce_Admin' => 'admin/class-mailchimp-woocommerce-admin.php',
'WP_Job' => 'includes/vendor/queue/classes/wp-job.php',
'WP_Queue' => 'includes/vendor/queue/classes/wp-queue.php',
'WP_Http_Worker' => 'includes/vendor/queue/classes/worker/wp-http-worker.php',
'WP_Worker' => 'includes/vendor/queue/classes/worker/wp-worker.php',
'Queue_Command' => 'includes/vendor/queue/classes/cli/queue-command.php',
);
// if the file exists, require it
$path = plugin_dir_path( __FILE__ );
if (array_key_exists($class, $classes) && file_exists($path.$classes[$class])) {
require $path.$classes[$class];
}
});
/**
* @return object
*/
function mailchimp_environment_variables() {
global $wp_version;
$o = get_option('mailchimp-woocommerce', false);
return (object) array(
'repo' => 'master',
'environment' => 'production',
'version' => '2.1.7',
'php_version' => phpversion(),
'wp_version' => (empty($wp_version) ? 'Unknown' : $wp_version),
'wc_version' => class_exists('WC') ? WC()->version : null,
'logging' => ($o && is_array($o) && isset($o['mailchimp_logging'])) ? $o['mailchimp_logging'] : 'standard',
);
}
// Add WP CLI commands
if (defined( 'WP_CLI' ) && WP_CLI) {
try {
/**
* Service push to MailChimp
*
* <type>
* : product_sync order_sync order product
*/
function mailchimp_cli_push_command( $args, $assoc_args ) {
if (is_array($args) && isset($args[0])) {
switch($args[0]) {
case 'product_sync':
wp_queue(new MailChimp_WooCommerce_Process_Products());
WP_CLI::success("queued up the product sync!");
break;
case 'order_sync':
wp_queue(new MailChimp_WooCommerce_Process_Orders());
WP_CLI::success("queued up the order sync!");
break;
case 'order':
if (!isset($args[1])) {
wp_die('You must specify an order id as the 2nd parameter.');
}
wp_queue(new MailChimp_WooCommerce_Single_Order($args[1]));
WP_CLI::success("queued up the order {$args[1]}!");
break;
case 'product':
if (!isset($args[1])) {
wp_die('You must specify a product id as the 2nd parameter.');
}
wp_queue(new MailChimp_WooCommerce_Single_Product($args[1]));
WP_CLI::success("queued up the product {$args[1]}!");
break;
}
}
};
WP_CLI::add_command( 'mailchimp_push', 'mailchimp_cli_push_command');
WP_CLI::add_command( 'queue', 'Queue_Command' );
} catch (\Exception $e) {}
}
if (!function_exists( 'wp_queue')) {
/**
* WP queue.
*
* @param WP_Job $job
* @param int $delay
*/
function wp_queue( WP_Job $job, $delay = 0 ) {
global $wp_queue;
if (empty($wp_queue)) {
$wp_queue = new WP_Queue();
}
$wp_queue->push( $job, $delay );
do_action( 'wp_queue_job_pushed', $job );
}
}
/**
* @return bool
*/
function mailchimp_should_init_queue() {
return mailchimp_detect_admin_ajax() && mailchimp_is_configured() && !mailchimp_running_in_console() && !mailchimp_http_worker_is_running();
}
/**
* @return bool
*/
function mailchimp_is_configured() {
return (bool) (mailchimp_get_api_key() && mailchimp_get_list_id());
}
/**
* @return bool|int
*/
function mailchimp_get_api_key() {
return mailchimp_get_option('mailchimp_api_key', false);
}
/**
* @return bool|int
*/
function mailchimp_get_list_id() {
return mailchimp_get_option('mailchimp_list', false);
}
/**
* @return string
*/
function mailchimp_get_store_id() {
$store_id = mailchimp_get_data('store_id', false);
if (empty($store_id)) {
mailchimp_set_data('store_id', $store_id = uniqid(), 'yes');
}
return $store_id;
}
/**
* @return bool|MailChimp_WooCommerce_MailChimpApi
*/
function mailchimp_get_api() {
if (($key = mailchimp_get_api_key())) {
return new MailChimp_WooCommerce_MailChimpApi($key);
}
return false;
}
/**
* @param $key
* @param null $default
* @return null
*/
function mailchimp_get_option($key, $default = null) {
$options = get_option('mailchimp-woocommerce');
if (!is_array($options)) {
return $default;
}
if (!array_key_exists($key, $options)) {
return $default;
}
return $options[$key];
}
/**
* @param $key
* @param null $default
* @return mixed
*/
function mailchimp_get_data($key, $default = null) {
return get_option('mailchimp-woocommerce-'.$key, $default);
}
/**
* @param $key
* @param $value
* @param string $autoload
* @return bool
*/
function mailchimp_set_data($key, $value, $autoload = 'yes') {
return update_option('mailchimp-woocommerce-'.$key, $value, $autoload);
}
/**
* @param $date
* @return DateTime
*/
function mailchimp_date_utc($date) {
$timezone = wc_timezone_string();
if (is_numeric($date)) {
$stamp = $date;
$date = new \DateTime('now', new DateTimeZone($timezone));
$date->setTimestamp($stamp);
} else {
$date = new \DateTime($date, new DateTimeZone($timezone));
}
$date->setTimezone(new DateTimeZone('UTC'));
return $date;
}
/**
* @param $date
* @return DateTime
*/
function mailchimp_date_local($date) {
$timezone = mailchimp_get_option('store_timezone', 'America/New_York');
if (is_numeric($date)) {
$stamp = $date;
$date = new \DateTime('now', new DateTimeZone('UTC'));
$date->setTimestamp($stamp);
} else {
$date = new \DateTime($date, new DateTimeZone('UTC'));
}
$date->setTimezone(new DateTimeZone($timezone));
return $date;
}
/**
* @param array $data
* @return mixed
*/
function mailchimp_array_remove_empty($data) {
if (empty($data) || !is_array($data)) {
return array();
}
foreach ($data as $key => $value) {
if ($value === null || $value === '' || (is_array($value) && empty($value))) {
unset($data[$key]);
}
}
return $data;
}
/**
* @return array
*/
function mailchimp_get_timezone_list() {
$zones_array = array();
$timestamp = time();
$current = date_default_timezone_get();
foreach(timezone_identifiers_list() as $key => $zone) {
date_default_timezone_set($zone);
$zones_array[$key]['zone'] = $zone;
$zones_array[$key]['diff_from_GMT'] = 'UTC/GMT ' . date('P', $timestamp);
}
date_default_timezone_set($current);
return $zones_array;
}
/**
* @return bool
*/
function mailchimp_check_woocommerce_plugin_status()
{
// if you are using a custom folder name other than woocommerce just define the constant to TRUE
if (defined("RUNNING_CUSTOM_WOOCOMMERCE") && RUNNING_CUSTOM_WOOCOMMERCE === true) {
return true;
}
// it the plugin is active, we're good.
if (in_array('woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option('active_plugins')))) {
return true;
}
// lets check for network activation woo installs now too.
if (function_exists('is_plugin_active_for_network')) {
return is_plugin_active_for_network( 'woocommerce/woocommerce.php');
}
return false;
}
/**
* Get all the registered image sizes along with their dimensions
*
* @global array $_wp_additional_image_sizes
*
* @link http://core.trac.wordpress.org/ticket/18947 Reference ticket
*
* @return array $image_sizes The image sizes
*/
function mailchimp_woocommerce_get_all_image_sizes() {
global $_wp_additional_image_sizes;
$image_sizes = array();
$default_image_sizes = get_intermediate_image_sizes();
foreach ($default_image_sizes as $size) {
$image_sizes[$size]['width'] = intval( get_option("{$size}_size_w"));
$image_sizes[$size]['height'] = intval( get_option("{$size}_size_h"));
$image_sizes[$size]['crop'] = get_option("{$size}_crop") ? get_option("{$size}_crop") : false;
}
if (isset($_wp_additional_image_sizes) && count($_wp_additional_image_sizes)) {
$image_sizes = array_merge( $image_sizes, $_wp_additional_image_sizes );
}
return $image_sizes;
}
/**
* @return array
*/
function mailchimp_woocommerce_get_all_image_sizes_list() {
$response = array();
foreach (mailchimp_woocommerce_get_all_image_sizes() as $key => $data) {
$label = ucwords(str_replace('_', ' ', $key));
$response[$key] = "{$label} ({$data['width']} x {$data['height']})";
}
return $response;
}
/**
* The code that runs during plugin activation.
* This action is documented in includes/class-mailchimp-woocommerce-activator.php
*/
function activate_mailchimp_woocommerce() {
// if we don't have woocommerce we need to display a horrible error message before the plugin is installed.
if (!mailchimp_check_woocommerce_plugin_status()) {
// Deactivate the plugin
deactivate_plugins(__FILE__);
$error_message = __('The MailChimp For WooCommerce plugin requires the <a href="http://wordpress.org/extend/plugins/woocommerce/">WooCommerce</a> plugin to be active!', 'woocommerce');
wp_die($error_message);
}
MailChimp_WooCommerce_Activator::activate();
}
/**
* Create the queue tables
*/
function install_mailchimp_queue() {
MailChimp_WooCommerce_Activator::create_queue_tables();
}
/**
* The code that runs during plugin deactivation.
* This action is documented in includes/class-mailchimp-woocommerce-deactivator.php
*/
function deactivate_mailchimp_woocommerce() {
MailChimp_WooCommerce_Deactivator::deactivate();
}
/**
* @param $action
* @param $message
* @param null $data
*/
function mailchimp_debug($action, $message, $data = null) {
if (mailchimp_environment_variables()->logging === 'debug' && function_exists('wc_get_logger')) {
if (is_array($data) && !empty($data)) $message .= " :: ".wc_print_r($data, true);
wc_get_logger()->debug("{$action} :: {$message}", array('source' => 'mailchimp_woocommerce'));
}
}
/**
* @param $action
* @param $message
* @param array $data
* @return array|WP_Error
*/
function mailchimp_log($action, $message, $data = array()) {
if (mailchimp_environment_variables()->logging !== 'none' && function_exists('wc_get_logger')) {
if (is_array($data) && !empty($data)) $message .= " :: ".wc_print_r($data, true);
wc_get_logger()->notice("{$action} :: {$message}", array('source' => 'mailchimp_woocommerce'));
}
}
/**
* @param $action
* @param $message
* @param array $data
* @return array|WP_Error
*/
function mailchimp_error($action, $message, $data = array()) {
if (mailchimp_environment_variables()->logging !== 'none' && function_exists('wc_get_logger')) {
if ($message instanceof \Exception) $message = mailchimp_error_trace($message);
if (is_array($data) && !empty($data)) $message .= " :: ".wc_print_r($data, true);
wc_get_logger()->error("{$action} :: {$message}", array('source' => 'mailchimp_woocommerce'));
}
}
/**
* @param Exception $e
* @param string $wrap
* @return string
*/
function mailchimp_error_trace(\Exception $e, $wrap = "") {
$error = "{$e->getMessage()} on {$e->getLine()} in {$e->getFile()}";
if (empty($wrap)) return $error;
return "{$wrap} :: {$error}";
}
/**
* Determine if a given string contains a given substring.
*
* @param string $haystack
* @param string|array $needles
* @return bool
*/
function mailchimp_string_contains($haystack, $needles) {
foreach ((array) $needles as $needle) {
if ($needle != '' && mb_strpos($haystack, $needle) !== false) {
return true;
}
}
return false;
}
/**
* @return int
*/
function mailchimp_get_product_count() {
$posts = mailchimp_count_posts('product');
unset($posts['auto-draft'], $posts['trash']);
$total = 0;
foreach ($posts as $status => $count) {
$total += $count;
}
return $total;
}
/**
* @return int
*/
function mailchimp_get_order_count() {
$posts = mailchimp_count_posts('shop_order');
unset($posts['auto-draft'], $posts['trash']);
$total = 0;
foreach ($posts as $status => $count) {
$total += $count;
}
return $total;
}
/**
* @param $type
* @return array|null|object
*/
function mailchimp_count_posts($type) {
global $wpdb;
$query = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = %s GROUP BY post_status";
$posts = $wpdb->get_results( $wpdb->prepare($query, $type));
$response = array();
foreach ($posts as $post) {
$response[$post->post_status] = $post->num_posts;
}
return $response;
}
/**
* @return bool
*/
function mailchimp_update_connected_site_script() {
// pull the store ID
$store_id = mailchimp_get_store_id();
// if the api is configured
if ($store_id && ($api = mailchimp_get_api())) {
// if we have a store
if (($store = $api->getStore($store_id))) {
// handle the coupon sync if we don't have a flag that says otherwise.
$job = new MailChimp_WooCommerce_Process_Coupons();
if ($job->getData('sync.coupons.completed_at', false) === false) {
wp_queue($job);
}
// see if we have a connected site script url/fragment
$url = $store->getConnectedSiteScriptUrl();
$fragment = $store->getConnectedSiteScriptFragment();
// if it's not empty we need to set the values
if ($url && $fragment) {
// update the options for script_url and script_fragment
update_option('mailchimp-woocommerce-script_url', $url);
update_option('mailchimp-woocommerce-script_fragment', $fragment);
// check to see if the site is connected
if (!$api->checkConnectedSite($store_id)) {
// if it's not, connect it now.
$api->connectSite($store_id);
}
return true;
}
}
}
return false;
}
/**
* @return bool
*/
function mailchimp_detect_admin_ajax() {
if (defined('DOING_CRON') && DOING_CRON) return true;
if (!is_admin()) return false;
if (!defined('DOING_AJAX')) return false;
return DOING_AJAX;
}
/**
* @return string|false
*/
function mailchimp_get_connected_site_script_url() {
return get_option('mailchimp-woocommerce-script_url', false);
}
/**
* @return string|false
*/
function mailchimp_get_connected_site_script_fragment() {
return get_option('mailchimp-woocommerce-script_fragment', false);
}
/**
* @return bool
*/
function mailchimp_running_in_console() {
return (bool) (defined( 'DISABLE_WP_HTTP_WORKER' ) && true === DISABLE_WP_HTTP_WORKER);
}
/**
* @return bool
*/
function mailchimp_http_worker_is_running() {
return (bool) get_site_transient('http_worker_lock');
}
/**
* @return array|WP_Error
*/
function mailchimp_call_http_worker_manually() {
$action = 'http_worker';
$query_args = apply_filters('http_worker_query_args', array(
'action' => $action,
'nonce' => wp_create_nonce($action),
));
$query_url = apply_filters('http_worker_query_url', admin_url('admin-ajax.php'));
$post_args = apply_filters('http_worker_post_args', array(
'timeout' => 0.01,
'blocking' => false,
'cookies' => $_COOKIE,
'sslverify' => apply_filters('https_local_ssl_verify', false),
));
$url = add_query_arg($query_args, $query_url);
return wp_remote_post(esc_url_raw($url), $post_args);
}
function mailchimp_flush_queue_tables() {
try {
/** @var \ */
global $wpdb;
$wpdb->query($wpdb->prepare("TRUNCATE `{$wpdb->prefix}queue`", array()));
$wpdb->query($wpdb->prepare("TRUNCATE `{$wpdb->prefix}failed_jobs`", array()));
$wpdb->query($wpdb->prepare("TRUNCATE `{$wpdb->prefix}mailchimp_carts`", array()));
} catch (\Exception $e) {}
}
function mailchimp_flush_sync_pointers() {
// clean up the initial sync pointers
foreach (array('orders', 'products', 'coupons') as $resource_type) {
delete_option("mailchimp-woocommerce-sync.{$resource_type}.started_at");
delete_option("mailchimp-woocommerce-sync.{$resource_type}.completed_at");
delete_option("mailchimp-woocommerce-sync.{$resource_type}.current_page");
}
}
/**
* To be used when running clean up for uninstalls or re-installs.
*/
function mailchimp_clean_database() {
mailchimp_flush_queue_tables();
// clean up the initial sync pointers
mailchimp_flush_sync_pointers();
delete_option('mailchimp-woocommerce');
delete_option('mailchimp-woocommerce-store_id');
delete_option('mailchimp-woocommerce-sync.syncing');
delete_option('mailchimp-woocommerce-sync.started_at');
delete_option('mailchimp-woocommerce-sync.completed_at');
delete_option('mailchimp-woocommerce-validation.api.ping');
delete_option('mailchimp-woocommerce-cached-api-lists');
delete_option('mailchimp-woocommerce-cached-api-ping-check');
delete_option('mailchimp-woocommerce-errors.store_info');
}
function run_mailchimp_woocommerce() {
$env = mailchimp_environment_variables();
$plugin = new MailChimp_WooCommerce($env->environment, $env->version);
$plugin->run();
}
function mailchimp_woocommerce_add_meta_tags() {
echo '<meta name="referrer" content="always"/>';
}
function mailchimp_on_all_plugins_loaded() {
if (mailchimp_check_woocommerce_plugin_status()) {
add_action('wp_head', 'mailchimp_woocommerce_add_meta_tags');
run_mailchimp_woocommerce();
}
}

View File

@@ -0,0 +1,337 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 3/8/16
* Time: 2:22 PM
*/
class MailChimp_WooCommerce_Address
{
protected $type;
protected $name;
protected $address1;
protected $address2;
protected $city;
protected $province;
protected $province_code;
protected $postal_code;
protected $country;
protected $country_code;
protected $longitude;
protected $latitude;
protected $phone;
protected $company;
/**
* @return array
*/
public function getValidation()
{
return array(
'address1' => 'string',
'address2' => 'string',
'city' => 'string',
'province' => 'string',
'province_code' => 'string|digits:2',
'postal_code' => 'string',
'country' => 'string',
'country_code' => 'string|digits:2',
'latitude' => 'numeric',
'longitude' => 'numeric',
);
}
/**
* @return mixed
*/
public function getName()
{
return $this->name;
}
/**
* @param mixed $name
* @return MailChimp_WooCommerce_Address
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* @return mixed
*/
public function getAddress1()
{
return $this->address1;
}
/**
* @param mixed $address1
* @return MailChimp_WooCommerce_Address
*/
public function setAddress1($address1)
{
$this->address1 = $address1;
return $this;
}
/**
* @return mixed
*/
public function getAddress2()
{
return $this->address2;
}
/**
* @param mixed $address2
* @return MailChimp_WooCommerce_Address
*/
public function setAddress2($address2)
{
$this->address2 = $address2;
return $this;
}
/**
* @return mixed
*/
public function getCity()
{
return $this->city;
}
/**
* @param mixed $city
* @return MailChimp_WooCommerce_Address
*/
public function setCity($city)
{
$this->city = $city;
return $this;
}
/**
* @return mixed
*/
public function getProvince()
{
return $this->province;
}
/**
* @param mixed $province
* @return MailChimp_WooCommerce_Address
*/
public function setProvince($province)
{
$this->province = $province;
return $this;
}
/**
* @return mixed
*/
public function getProvinceCode()
{
return $this->province_code;
}
/**
* @param mixed $province_code
* @return MailChimp_WooCommerce_Address
*/
public function setProvinceCode($province_code)
{
$this->province_code = $province_code;
return $this;
}
/**
* @return mixed
*/
public function getPostalCode()
{
return $this->postal_code;
}
/**
* @param mixed $postal_code
* @return MailChimp_WooCommerce_Address
*/
public function setPostalCode($postal_code)
{
$this->postal_code = $postal_code;
return $this;
}
/**
* @return mixed
*/
public function getCountry()
{
return $this->country;
}
/**
* @param mixed $country
* @return MailChimp_WooCommerce_Address
*/
public function setCountry($country)
{
$this->country = $country;
return $this;
}
/**
* @return mixed
*/
public function getCountryCode()
{
return $this->country_code;
}
/**
* @param mixed $country_code
* @return MailChimp_WooCommerce_Address
*/
public function setCountryCode($country_code)
{
$this->country_code = $country_code;
return $this;
}
/**
* @return mixed
*/
public function getLongitude()
{
return $this->longitude;
}
/**
* @param mixed $longitude
* @return MailChimp_WooCommerce_Address
*/
public function setLongitude($longitude)
{
$this->longitude = $longitude;
return $this;
}
/**
* @return mixed
*/
public function getLatitude()
{
return $this->latitude;
}
/**
* @param mixed $latitude
* @return MailChimp_WooCommerce_Address
*/
public function setLatitude($latitude)
{
$this->latitude = $latitude;
return $this;
}
/**
* @return mixed
*/
public function getPhone()
{
return $this->phone;
}
/**
* @param mixed $phone
* @return MailChimp_WooCommerce_Address
*/
public function setPhone($phone)
{
$this->phone = $phone;
return $this;
}
/**
* @return mixed
*/
public function getCompany()
{
return $this->company;
}
/**
* @param mixed $company
* @return MailChimp_WooCommerce_Address
*/
public function setCompany($company)
{
$this->company = $company;
return $this;
}
/**
* @return array
*/
public function toArray()
{
return mailchimp_array_remove_empty(array(
'name' => (string) $this->name,
'address1' => (string) $this->address1,
'address2' => (string) $this->address2,
'city' => (string) $this->city,
'province' => (string) $this->province,
'province_code' => (string) $this->province_code,
'postal_code' => (string) $this->postal_code,
'country' => (string) $this->country,
'country_code' => (string) $this->country_code,
'longitude' => ($this->longitude ? (int) $this->longitude : null),
'latitude' => ($this->latitude ? (int) $this->latitude : null),
'phone' => (string) $this->phone,
'company' => (string) $this->company,
));
}
/**
* @param array $data
* @return MailChimp_WooCommerce_Address
*/
public function fromArray(array $data)
{
$singles = array(
'name', 'address1', 'address2', 'city',
'province', 'province_code', 'postal_code',
'country', 'country_code', 'longitude',
'phone', 'company',
);
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
return $this;
}
}

View File

@@ -0,0 +1,277 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/15/16
* Time: 1:26 PM
*/
class MailChimp_WooCommerce_Cart
{
protected $store_id;
protected $id;
protected $customer;
protected $campaign_id;
protected $checkout_url;
protected $currency_code;
protected $order_total;
protected $tax_total;
protected $lines = array();
/**
* @param $unique_id
* @return $this
*/
public function setId($unique_id)
{
$this->id = $unique_id;
return $this;
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @param $store_id
* @return $this
*/
public function setStoreID($store_id)
{
$this->store_id = $store_id;
return $this;
}
/**
* @return mixed
*/
public function getStoreID()
{
if (empty($this->store_id)) {
$this->store_id = mailchimp_get_store_id();
}
return $this->store_id;
}
/**
* @param MailChimp_WooCommerce_Customer $customer
* @return $this
*/
public function setCustomer(MailChimp_WooCommerce_Customer $customer)
{
$this->customer = $customer;
return $this;
}
/**
* @return MailChimp_WooCommerce_Customer
*/
public function getCustomer()
{
if (empty($this->customer)) {
$this->customer = new MailChimp_WooCommerce_Customer();
}
return $this->customer;
}
/**
* @param $id
* @return $this
*/
public function setCampaignID($id)
{
$this->campaign_id = $id;
return $this;
}
/**
* @return mixed
*/
public function getCampaignID()
{
return $this->campaign_id;
}
/**
* @param $url
* @return $this
*/
public function setCheckoutUrl($url)
{
$this->checkout_url = $url;
return $this;
}
/**
* @return string
*/
public function getCheckoutURL()
{
if (empty($this->checkout_url)) {
$this->checkout_url = wc_get_checkout_url();
}
return $this->checkout_url;
}
/**
* @param $code
* @return $this
*/
public function setCurrencyCode($code)
{
$this->currency_code = $code;
return $this;
}
/**
* @return string
*/
public function getCurrencyCode()
{
if (empty($this->currency_code)) {
$options = get_option('mailchimp-woocommerce', array());
$this->currency_code = isset($options['store_currency_code']) ? $options['store_currency_code'] : 'USD';
}
return $this->currency_code;
}
/**
* @param $total
* @return $this
*/
public function setOrderTotal($total)
{
$this->order_total = $total;
return $this;
}
/**
* @return float
*/
public function getOrderTotal()
{
return $this->order_total;
}
/**
* @param $total
* @return $this
*/
public function setTaxTotal($total)
{
$this->tax_total = $total;
return $this;
}
/**
* @return float
*/
public function getTaxTotal()
{
return $this->tax_total;
}
/**
* @param MailChimp_WooCommerce_LineItem $item
* @return $this
*/
public function addItem(MailChimp_WooCommerce_LineItem $item)
{
$this->lines[] = $item;
return $this;
}
/**
* @return array
*/
public function items()
{
return $this->lines;
}
/**
* @return mixed
*/
public function toArray()
{
return mailchimp_array_remove_empty(array(
'id' => (string) $this->getId(),
'customer' => $this->getCustomer()->toArray(),
'campaign_id' => (string) $this->getCampaignID(),
'checkout_url' => (string) $this->getCheckoutURL(),
'currency_code' => (string) $this->getCurrencyCode(),
'order_total' => floatval($this->getOrderTotal()),
'tax_total' => $this->getTaxTotal() > 0 ? floatval($this->getTaxTotal()) : null,
'lines' => array_map(function($item) {
return $item->toArray();
}, $this->items()),
));
}
/**
* @return array
*/
public function toArrayForUpdate()
{
return mailchimp_array_remove_empty(array(
'campaign_id' => (string) $this->getCampaignID(),
'checkout_url' => (string) $this->getCheckoutURL(),
'currency_code' => (string) $this->getCurrencyCode(),
'order_total' => $this->getOrderTotal(),
'tax_total' => ($this->getTaxTotal() > 0 ? $this->getTaxTotal() : null),
'lines' => array_map(function($item) {
return $item->toArray();
}, $this->items()),
));
}
/**
* @param array $data
* @return MailChimp_WooCommerce_Cart
*/
public function fromArray(array $data)
{
$singles = array(
'store_id', 'id', 'campaign_id', 'checkout_url',
'currency_code', 'order_total', 'tax_total',
);
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
if (array_key_exists('customer', $data) && is_array($data['customer'])) {
$customer = new MailChimp_WooCommerce_Customer();
$this->customer = $customer->fromArray($data['customer']);
}
if (array_key_exists('lines', $data) && is_array($data['lines'])) {
foreach ($data['lines'] as $line_item) {
$item = new MailChimp_WooCommerce_LineItem();
$this->lines[] = $item->fromArray($line_item);
}
}
return $this;
}
}

View File

@@ -0,0 +1,258 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 3/8/16
* Time: 2:16 PM
*/
class MailChimp_WooCommerce_Customer
{
protected $id = null;
protected $email_address = null;
protected $opt_in_status = null;
protected $company = null;
protected $first_name = null;
protected $last_name = null;
protected $orders_count = null;
protected $total_spent = null;
protected $address;
/**
* @return array
*/
public function getValidation()
{
return array(
'id' => 'required',
'email_address' => 'required|email',
'opt_in_status' => 'required|boolean',
'company' => 'string',
'first_name' => 'string',
'last_name' => 'string',
'orders_count' => 'integer',
'total_spent' => 'integer',
);
}
/**
* @return null
*/
public function getId()
{
return $this->id;
}
/**
* @param null $id
* @return MailChimp_WooCommerce_Customer
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return null
*/
public function getEmailAddress()
{
return $this->email_address;
}
/**
* @param null $email_address
* @return MailChimp_WooCommerce_Customer
*/
public function setEmailAddress($email_address)
{
$this->email_address = $email_address;
return $this;
}
/**
* @return null
*/
public function getOptInStatus()
{
return $this->opt_in_status;
}
/**
* @param null $opt_in_status
* @return MailChimp_WooCommerce_Customer
*/
public function setOptInStatus($opt_in_status)
{
$this->opt_in_status = $opt_in_status;
return $this;
}
/**
* @return null
*/
public function getCompany()
{
return $this->company;
}
/**
* @param null $company
* @return MailChimp_WooCommerce_Customer
*/
public function setCompany($company)
{
$this->company = $company;
return $this;
}
/**
* @return null
*/
public function getFirstName()
{
return $this->first_name;
}
/**
* @param null $first_name
* @return MailChimp_WooCommerce_Customer
*/
public function setFirstName($first_name)
{
$this->first_name = $first_name;
return $this;
}
/**
* @return null
*/
public function getLastName()
{
return $this->last_name;
}
/**
* @param null $last_name
* @return MailChimp_WooCommerce_Customer
*/
public function setLastName($last_name)
{
$this->last_name = $last_name;
return $this;
}
/**
* @return null
*/
public function getOrdersCount()
{
return $this->orders_count;
}
/**
* @param null $orders_count
* @return MailChimp_WooCommerce_Customer
*/
public function setOrdersCount($orders_count)
{
$this->orders_count = $orders_count;
return $this;
}
/**
* @return null
*/
public function getTotalSpent()
{
return $this->total_spent;
}
/**
* @param null $total_spent
* @return MailChimp_WooCommerce_Customer
*/
public function setTotalSpent($total_spent)
{
$this->total_spent = $total_spent;
return $this;
}
/**
* @return MailChimp_WooCommerce_Address
*/
public function getAddress()
{
if (empty($this->address)) {
$this->address = new MailChimp_WooCommerce_Address();
}
return $this->address;
}
/**
* @param MailChimp_WooCommerce_Address $address
* @return MailChimp_WooCommerce_Customer
*/
public function setAddress(MailChimp_WooCommerce_Address $address)
{
$this->address = $address;
return $this;
}
/**
* @return array
*/
public function toArray()
{
$address = $this->getAddress()->toArray();
return mailchimp_array_remove_empty(array(
'id' => (string) $this->getId(),
'email_address' => (string) $this->getEmailAddress(),
'opt_in_status' => $this->getOptInStatus(),
'company' => (string) $this->getCompany(),
'first_name' => (string) $this->getFirstName(),
'last_name' => (string) $this->getLastName(),
'orders_count' => (int) $this->getOrdersCount(),
'total_spent' => floatval(number_format($this->getTotalSpent(), 2)),
'address' => (empty($address) ? null : $address),
));
}
/**
* @param array $data
* @return MailChimp_WooCommerce_Customer
*/
public function fromArray(array $data)
{
$singles = array(
'id', 'email_address', 'opt_in_status', 'company',
'first_name', 'last_name', 'orders_count', 'total_spent',
);
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
if (array_key_exists('address', $data) && is_array($data['address'])) {
$address = new MailChimp_WooCommerce_Address();
$this->address = $address->fromArray($data['address']);
}
return $this;
}
}

View File

@@ -0,0 +1,180 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 3/8/16
* Time: 2:16 PM
*/
class MailChimp_WooCommerce_LineItem
{
protected $id;
protected $product_id;
protected $product_variant_id;
protected $quantity;
protected $price;
/**
* @return array
*/
public function getValidation()
{
return array(
'id' => 'required|string',
'product_id' => 'required|string',
'product_variant_id' => 'required|string',
'quantity' => 'required|integer',
'price' => 'required|numeric',
);
}
/**
* @param $id
* @param $product_id
* @param $variant_id
* @param $quantity
* @param $price
* @return MailChimp_WooCommerce_LineItem
*/
public static function make($id, $product_id, $variant_id, $quantity, $price)
{
$item = new MailChimp_WooCommerce_LineItem();
$item->id = $id;
$item->product_id = $product_id;
$item->product_variant_id = $variant_id;
$item->quantity = $quantity;
$item->price = $price;
return $item;
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @param mixed $id
* @return MailChimp_WooCommerce_LineItem
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return mixed
*/
public function getProductId()
{
return $this->product_id;
}
/**
* @param mixed $product_id
* @return MailChimp_WooCommerce_LineItem
*/
public function setProductId($product_id)
{
$this->product_id = $product_id;
return $this;
}
/**
* @return mixed
*/
public function getProductVariantId()
{
return $this->product_variant_id;
}
/**
* @param mixed $product_variant_id
* @return MailChimp_WooCommerce_LineItem
*/
public function setProductVariantId($product_variant_id)
{
$this->product_variant_id = $product_variant_id;
return $this;
}
/**
* @return mixed
*/
public function getQuantity()
{
return $this->quantity;
}
/**
* @param mixed $quantity
* @return MailChimp_WooCommerce_LineItem
*/
public function setQuantity($quantity)
{
$this->quantity = $quantity;
return $this;
}
/**
* @return mixed
*/
public function getPrice()
{
return $this->price;
}
/**
* @param mixed $price
* @return MailChimp_WooCommerce_LineItem
*/
public function setPrice($price)
{
$this->price = $price;
return $this;
}
/**
* @return array
*/
public function toArray()
{
return mailchimp_array_remove_empty(array(
'id' => (string) $this->id,
'product_id' => (string) $this->product_id,
'product_variant_id' => (string) $this->product_variant_id,
'quantity' => (int) $this->quantity,
'price' => (string) $this->price,
));
}
/**
* @param array $data
* @return MailChimp_WooCommerce_LineItem
*/
public function fromArray(array $data)
{
$singles = array(
'id', 'product_id', 'product_variant_id', 'quantity', 'price',
);
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
return $this;
}
}

View File

@@ -0,0 +1,547 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 3/8/16
* Time: 2:16 PM
*/
class MailChimp_WooCommerce_Order
{
protected $id = null;
protected $landing_site = null;
protected $customer = null;
protected $campaign_id = null;
protected $financial_status = null;
protected $fulfillment_status = null;
protected $currency_code = null;
protected $order_total = null;
protected $tax_total = null;
protected $discount_total = null;
protected $shipping_total = null;
protected $updated_at_foreign = null;
protected $processed_at_foreign = null;
protected $cancelled_at_foreign = null;
protected $order_url = null;
protected $shipping_address = null;
protected $billing_address = null;
protected $lines = array();
protected $confirm_and_paid = false;
protected $promos = array();
protected $is_amazon_order = false;
/**
* @param $bool
* @return $this
*/
public function flagAsAmazonOrder($bool)
{
$this->is_amazon_order = (bool) $bool;
return $this;
}
/**
* @return bool
*/
public function isFlaggedAsAmazonOrder()
{
return (bool) $this->is_amazon_order;
}
/**
* @return array
*/
public function getValidation()
{
return array(
'id' => 'required|string',
'landing_site' => 'required|string',
'customer' => 'required',
'campaign_id' => 'string',
'financial_status' => 'string',
'fulfillment_status' => 'string',
'currency_code' => 'required|currency_code',
'order_total' => 'required|numeric',
'tax_total' => 'numeric',
'discount_total' => 'numeric',
'processed_at_foreign' => 'date',
'updated_at_foreign' => 'date',
'cancelled_at_foreign' => 'date',
'order_url' => 'string',
'lines' => 'required|array',
);
}
/**
* @param $id
* @return MailChimp_WooCommerce_Order
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return null|string
*/
public function getId()
{
return $this->id;
}
/**
* @param $landing_site
* @return $this
*/
public function setLandingSite($landing_site)
{
$this->landing_site = $landing_site;
return $this;
}
/**
* @return null|string
*/
public function getLandingSite()
{
return $this->landing_site;
}
/**
* @param MailChimp_WooCommerce_Customer $customer
* @return MailChimp_WooCommerce_Order
*/
public function setCustomer(MailChimp_WooCommerce_Customer $customer)
{
$this->customer = $customer;
return $this;
}
/**
* @return null|MailChimp_WooCommerce_Customer
*/
public function getCustomer()
{
if (empty($this->customer)) {
$this->customer = new MailChimp_WooCommerce_Customer();
}
return $this->customer;
}
/**
* @param MailChimp_WooCommerce_LineItem $item
* @return $this
*/
public function addItem(MailChimp_WooCommerce_LineItem $item)
{
$this->lines[] = $item;
return $this;
}
/**
* @param $code
* @param $amount
* @param bool $is_percentage
* @return $this
*/
public function addDiscount($code, $amount, $is_percentage = false)
{
$this->promos[] = array(
'code' => $code,
'amount_discounted' => $amount,
'type' => $is_percentage ? 'percent' : 'fixed'
);
return $this;
}
/**
* @return array
*/
public function discounts()
{
return $this->promos;
}
/**
* @return array
*/
public function items()
{
return $this->lines;
}
/**
* @return null
*/
public function getCampaignId()
{
return $this->campaign_id;
}
/**
* @param null $campaign_id
* @return MailChimp_WooCommerce_Order
*/
public function setCampaignId($campaign_id)
{
$this->campaign_id = $campaign_id;
return $this;
}
/**
* @return null
*/
public function getFinancialStatus()
{
return $this->financial_status;
}
/**
* @param null $financial_status
* @return MailChimp_WooCommerce_Order
*/
public function setFinancialStatus($financial_status)
{
$this->financial_status = $financial_status;
return $this;
}
/**
* @return null
*/
public function getFulfillmentStatus()
{
return $this->fulfillment_status;
}
/**
* @param null $fulfillment_status
* @return MailChimp_WooCommerce_Order
*/
public function setFulfillmentStatus($fulfillment_status)
{
$this->fulfillment_status = $fulfillment_status;
return $this;
}
/**
* @return null
*/
public function getCurrencyCode()
{
return $this->currency_code;
}
/**
* @param null $currency_code
* @return MailChimp_WooCommerce_Order
*/
public function setCurrencyCode($currency_code)
{
$this->currency_code = $currency_code;
return $this;
}
/**
* @return mixed
*/
public function getOrderTotal()
{
return $this->order_total;
}
/**
* @param mixed $order_total
* @return MailChimp_WooCommerce_Order
*/
public function setOrderTotal($order_total)
{
$this->order_total = $order_total;
return $this;
}
/**
* @param $url
* @return $this
*/
public function setOrderURL($url)
{
if (($url = wp_http_validate_url($url))) {
$this->order_url = $url;
}
return $this;
}
/**
* @return string
*/
public function getOrderURL()
{
return $this->order_url;
}
/**
* @return mixed
*/
public function getTaxTotal()
{
return $this->tax_total;
}
/**
* @param mixed $tax_total
* @return MailChimp_WooCommerce_Order
*/
public function setTaxTotal($tax_total)
{
$this->tax_total = $tax_total;
return $this;
}
/**
* @return mixed
*/
public function getShippingTotal()
{
return $this->shipping_total;
}
/**
* @param mixed $shipping_total
* @return MailChimp_WooCommerce_Order
*/
public function setShippingTotal($shipping_total)
{
$this->shipping_total = $shipping_total;
return $this;
}
/**
* @return mixed
*/
public function getDiscountTotal()
{
return $this->discount_total;
}
/**
* @param mixed $discount_total
* @return MailChimp_WooCommerce_Order
*/
public function setDiscountTotal($discount_total)
{
$this->discount_total = $discount_total;
return $this;
}
/**
* @param \DateTime $time
* @return $this
*/
public function setProcessedAt(\DateTime $time)
{
$this->processed_at_foreign = $time->format('Y-m-d H:i:s');
return $this;
}
/**
* @return null
*/
public function getProcessedAt()
{
return $this->processed_at_foreign;
}
/**
* @param \DateTime $time
* @return $this
*/
public function setCancelledAt(\DateTime $time)
{
$this->cancelled_at_foreign = $time->format('Y-m-d H:i:s');
return $this;
}
/**
* @return null
*/
public function getCancelledAt()
{
return $this->cancelled_at_foreign;
}
/**
* @param \DateTime $time
* @return $this
*/
public function setUpdatedAt(\DateTime $time)
{
$this->updated_at_foreign = $time->format('Y-m-d H:i:s');
return $this;
}
/**
* @return null
*/
public function getUpdatedAt()
{
return $this->updated_at_foreign;
}
/**
* @param $bool
* @param $bool
* @return $this
*/
public function confirmAndPay($bool)
{
$this->confirm_and_paid = (bool) $bool;
return $this;
}
/**
* @return bool
*/
public function shouldConfirmAndPay()
{
return $this->confirm_and_paid;
}
/**
* @param MailChimp_WooCommerce_Address $address
* @return $this
*/
public function setShippingAddress(MailChimp_WooCommerce_Address $address)
{
$this->shipping_address = $address;
return $this;
}
/**
* @return MailChimp_WooCommerce_Address
*/
public function getShippingAddress()
{
if (empty($this->shipping_address)) {
$this->shipping_address = new MailChimp_WooCommerce_Address();
}
return $this->shipping_address;
}
/**
* @param MailChimp_WooCommerce_Address $address
* @return $this
*/
public function setBillingAddress(MailChimp_WooCommerce_Address $address)
{
$this->billing_address = $address;
return $this;
}
/**
* @return MailChimp_WooCommerce_Address
*/
public function getBillingAddress()
{
if (empty($this->billing_address)) {
$this->billing_address = new MailChimp_WooCommerce_Address();
}
return $this->billing_address;
}
/**
* @return array
*/
public function toArray()
{
return mailchimp_array_remove_empty(array(
'id' => (string) $this->getId(),
'landing_site' => (string) $this->getLandingSite(),
'customer' => $this->getCustomer()->toArray(),
'campaign_id' => (string) $this->getCampaignId(),
'financial_status' => (string) $this->getFinancialStatus(),
'fulfillment_status' => (string) $this->getFulfillmentStatus(),
'currency_code' => (string) $this->getCurrencyCode(),
'order_total' => floatval($this->getOrderTotal()),
'order_url' => (string) $this->getOrderURL(),
'tax_total' => floatval($this->getTaxTotal()),
'discount_total' => floatval($this->getDiscountTotal()),
'shipping_total' => floatval($this->getShippingTotal()),
'processed_at_foreign' => (string) $this->getProcessedAt(),
'cancelled_at_foreign' => (string) $this->getCancelledAt(),
'updated_at_foreign' => (string) $this->getUpdatedAt(),
'shipping_address' => $this->getShippingAddress()->toArray(),
'billing_address' => $this->getBillingAddress()->toArray(),
'promos' => !empty($this->promos) ? $this->promos : null,
'lines' => array_map(function ($item) {
/** @var MailChimp_WooCommerce_LineItem $item */
return $item->toArray();
}, $this->items()),
));
}
/**
* @param array $data
* @return MailChimp_WooCommerce_Order
*/
public function fromArray(array $data)
{
$singles = array(
'id', 'landing_site', 'campaign_id', 'financial_status', 'fulfillment_status',
'currency_code', 'order_total', 'order_url', 'tax_total', 'discount_total', 'processed_at_foreign',
'cancelled_at_foreign', 'updated_at_foreign'
);
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
if (array_key_exists('shipping_address', $data) && is_array($data['shipping_address'])) {
$shipping = new MailChimp_WooCommerce_Address();
$this->shipping_address = $shipping->fromArray($data['shipping_address']);
}
if (array_key_exists('billing_address', $data) && is_array($data['billing_address'])) {
$billing = new MailChimp_WooCommerce_Address();
$this->billing_address = $billing->fromArray($data['billing_address']);
}
if (array_key_exists('promos', $data)) {
$this->promos = $data['promos'];
}
if (array_key_exists('lines', $data) && is_array($data['lines'])) {
$this->lines = array();
foreach ($data['lines'] as $line_item) {
$item = new MailChimp_WooCommerce_LineItem();
$this->lines[] = $item->fromArray($line_item);
}
}
return $this;
}
}

View File

@@ -0,0 +1,250 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 3/8/16
* Time: 2:17 PM
*/
class MailChimp_WooCommerce_ProductVariation
{
protected $id = null;
protected $title = null;
protected $url = null;
protected $sku = null;
protected $price = null;
protected $inventory_quantity = null;
protected $image_url = null;
protected $backorders = null;
protected $visibility = null;
/**
* @return array
*/
public function getValidation()
{
return array(
'id' => 'required|string',
'title' => 'required|string',
'url' => 'url',
'sku' => 'string',
'price' => 'numeric',
'inventory_quantity' => 'integer',
'image_url' => 'url',
'backorders' => 'string',
'visibility' => 'string',
);
}
/**
* @return null
*/
public function getId()
{
return $this->id;
}
/**
* @param null $id
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return null
*/
public function getTitle()
{
return $this->title;
}
/**
* @param null $title
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* @return null
*/
public function getUrl()
{
return $this->url;
}
/**
* @param null $url
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setUrl($url)
{
$this->url = $url;
return $this;
}
/**
* @return null
*/
public function getSku()
{
return $this->sku;
}
/**
* @param null $sku
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setSku($sku)
{
$this->sku = $sku;
return $this;
}
/**
* @return null
*/
public function getPrice()
{
return $this->price;
}
/**
* @param null $price
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setPrice($price)
{
$this->price = $price;
return $this;
}
/**
* @return null
*/
public function getInventoryQuantity()
{
return $this->inventory_quantity;
}
/**
* @param null $inventory_quantity
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setInventoryQuantity($inventory_quantity)
{
$this->inventory_quantity = $inventory_quantity;
return $this;
}
/**
* @return null
*/
public function getImageUrl()
{
return !empty($this->image_url) ? $this->image_url : null;
}
/**
* @param null $image_url
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setImageUrl($image_url)
{
$this->image_url = $image_url;
return $this;
}
/**
* @return null
*/
public function getBackorders()
{
return $this->backorders;
}
/**
* @param null $backorders
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setBackorders($backorders)
{
$this->backorders = $backorders;
return $this;
}
/**
* @return null
*/
public function getVisibility()
{
return $this->visibility;
}
/**
* @param null $visibility
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setVisibility($visibility)
{
$this->visibility = $visibility;
return $this;
}
/**
* @return array
*/
public function toArray()
{
return mailchimp_array_remove_empty(array(
'id' => (string) $this->getId(),
'title' => $this->getTitle(),
'url' => (string) $this->getUrl(),
'sku' => (string) $this->getSku(),
'price' => $this->getPrice(),
'inventory_quantity' => (int) $this->getInventoryQuantity(),
'image_url' => (string) $this->getImageUrl(),
'backorders' => $this->getBackorders() ? 'true' : 'false',
'visibility' => (string) $this->getVisibility(),
));
}
/**
* @param array $data
* @return MailChimp_WooCommerce_ProductVariation
*/
public function fromArray(array $data)
{
$singles = array(
'id', 'title', 'url', 'sku',
'price', 'inventory_quantity', 'image_url', 'backorders',
'visibility',
);
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
return $this;
}
}

View File

@@ -0,0 +1,282 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 3/8/16
* Time: 2:17 PM
*/
class MailChimp_WooCommerce_Product
{
protected $id;
protected $title;
protected $handle = null;
protected $url = null;
protected $description = null;
protected $type = null;
protected $vendor = null;
protected $image_url = null;
protected $variants = array();
protected $published_at_foreign = null;
/**
* @return array
*/
public function getValidation()
{
return array(
'id' => 'required|string',
'title' => 'required|string',
'handle' => 'string',
'url' => 'url',
'description' => 'string',
'type' => 'string',
'vendor' => 'string',
'image_url' => 'url',
'variants' => 'required|array',
'published_at_foreign' => 'date',
);
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @param mixed $id
* @return MailChimp_WooCommerce_Product
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return mixed
*/
public function getTitle()
{
return $this->title;
}
/**
* @param mixed $title
* @return MailChimp_WooCommerce_Product
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* @return null
*/
public function getHandle()
{
return $this->handle;
}
/**
* @param null $handle
* @return MailChimp_WooCommerce_Product
*/
public function setHandle($handle)
{
$this->handle = $handle;
return $this;
}
/**
* @return null
*/
public function getUrl()
{
return $this->url;
}
/**
* @param null $url
* @return MailChimp_WooCommerce_Product
*/
public function setUrl($url)
{
$this->url = $url;
return $this;
}
/**
* @return null
*/
public function getDescription()
{
return $this->description;
}
/**
* @param null $description
* @return MailChimp_WooCommerce_Product
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* @return null
*/
public function getType()
{
return $this->type;
}
/**
* @param null $type
* @return MailChimp_WooCommerce_Product
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* @return null
*/
public function getVendor()
{
return $this->vendor;
}
/**
* @param null $vendor
* @return MailChimp_WooCommerce_Product
*/
public function setVendor($vendor)
{
$this->vendor = $vendor;
return $this;
}
/**
* @return null
*/
public function getImageUrl()
{
return $this->image_url;
}
/**
* @param null $image_url
* @return MailChimp_WooCommerce_Product
*/
public function setImageUrl($image_url)
{
$this->image_url = $image_url;
return $this;
}
/**
* @return array
*/
public function getVariations()
{
return $this->variants;
}
/**
* @param MailChimp_WooCommerce_ProductVariation $variation
* @return MailChimp_WooCommerce_Product
*/
public function addVariant(MailChimp_WooCommerce_ProductVariation $variation)
{
$this->variants[] = $variation;
return $this;
}
/**
* @return string
*/
public function getPublishedAtForeign()
{
return $this->published_at_foreign;
}
/**
* @param \DateTime $time
* @return MailChimp_WooCommerce_Product
*/
public function setPublishedAtForeign(\DateTime $time)
{
$this->published_at_foreign = $time->format('Y-m-d H:i:s');
return $this;
}
/**
* @return array
*/
public function toArray()
{
return mailchimp_array_remove_empty(array(
'id' => (string) $this->getId(),
'title' => $this->getTitle(),
'handle' => (string) $this->getHandle(),
'url' => (string) $this->getUrl(),
'description' => (string) $this->getDescription(),
'type' => (string) $this->getType(),
'vendor' => (string) $this->getVendor(),
'image_url' => (string) $this->getImageUrl(),
'variants' => array_map(function ($item) {
return $item->toArray();
}, $this->getVariations()),
'published_at_foreign' => (string) $this->getPublishedAtForeign(),
));
}
/**
* @param array $data
* @return MailChimp_WooCommerce_Product
*/
public function fromArray(array $data)
{
$singles = array(
'id', 'title', 'handle', 'url',
'description', 'type', 'vendor', 'image_url',
'published_at_foreign',
);
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
if (array_key_exists('variants', $data) && is_array($data['variants'])) {
$this->variants = array();
foreach ($data['variants'] as $variant) {
$variation = new MailChimp_WooCommerce_ProductVariation();
$this->variants[] = $variation->fromArray($variant);
}
}
return $this;
}
}

View File

@@ -0,0 +1,230 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 6/13/17
* Time: 1:19 PM
*/
class MailChimp_WooCommerce_PromoCode
{
/**
* @var string
* @title Promo Rule Foreign ID
* @description A unique identifier for the promo code
*/
protected $id;
/**
* @var string
* @title Code
* @required
* @description The discount code
*/
protected $code;
/**
* @var string
* @title Promo Redemption Url
* @required
* @description The url that should be used in the promotion campaign. Eg. A url that applies promo code directly at checkout or a url that points to sale page. Use store url if promotion url is not available.
*/
protected $redemption_url;
/**
* @var string
* @title Description
* @default null
* @description Number of times promo code has been used.
*/
protected $usage_count;
/**
* @var boolean
* @title Enabled
* @default true
* @description Whether the promo code is currently enabled. ***
*/
protected $enabled;
/**
* @var \DateTime
* @title Start Time
* @default null
* @description The date and time when the promotion starts in ISO 8601 format
*/
protected $created_at_foreign;
/**
* @var \DateTime
* @title Start Time
* @default null
* @description The date and time when the promotion starts in ISO 8601 format
*/
protected $updated_at_foreign;
/**
* @var MailChimp_WooCommerce_PromoRule|null
*/
protected $promo_rule;
/**
* @return array
*/
public function getValidation()
{
return [
'id' => 'required',
'code' => 'required',
'redemption_url' => 'required',
'usage_count' => 'integer',
'created_at_foreign' => 'date',
'updated_at_foreign' => 'date',
];
}
/**
* @param MailChimp_WooCommerce_PromoRule $promo
* @return MailChimp_WooCommerce_PromoCode
*/
public function attachPromoRule(MailChimp_WooCommerce_PromoRule $promo)
{
$this->promo_rule = $promo;
return $this;
}
/**
* @return MailChimp_WooCommerce_PromoRule|null
*/
public function getAttachedPromoRule()
{
return $this->promo_rule;
}
/**
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* @param null $id
* @return MailChimp_WooCommerce_PromoCode
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return string
*/
public function getCode()
{
return $this->code;
}
/**
* @param string $code
* @return MailChimp_WooCommerce_PromoCode
*/
public function setCode($code)
{
$this->code = $code;
return $this;
}
/**
* @return string
*/
public function getRedemptionURL()
{
return $this->redemption_url;
}
/**
* @param string $url
* @return MailChimp_WooCommerce_PromoCode
*/
public function setRedemptionURL($url)
{
$this->redemption_url = $url;
return $this;
}
public function getUsageCount()
{
return $this->usage_count;
}
/**
* @param $count
* @return MailChimp_WooCommerce_PromoCode
*/
public function setUsageCount($count)
{
$this->usage_count = $count;
return $this;
}
/**
* @param $enabled
* @return MailChimp_WooCommerce_PromoCode
*/
public function setEnabled($enabled)
{
$this->enabled = (bool) $enabled;
return $this;
}
/**
* @return bool
*/
public function isEnabled()
{
return (bool) $this->enabled;
}
/**
* @return array
*/
public function toArray()
{
return mailchimp_array_remove_empty([
'id' => (string) $this->getId(),
'code' => (string) $this->getCode(),
'redemption_url' => (string) $this->getRedemptionURL(),
'usage_count' => $this->getUsageCount(),
'enabled' => $this->isEnabled(),
]);
}
/**
* @param array $data
* @return MailChimp_WooCommerce_PromoCode
*/
public function fromArray(array $data)
{
$singles = [
'id', 'code', 'usage_count', 'enabled',
'redemption_url', 'created_at_foreign', 'updated_at_foreign',
];
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
return $this;
}
}

View File

@@ -0,0 +1,405 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 6/13/17
* Time: 1:19 PM
*/
class MailChimp_WooCommerce_PromoRule
{
/**
* @var string
* @title Promo Rule Foreign ID
* @default = null
* @description
* A unique identifier for the promo rule. If Ecomm platform does not support promo rule,
* use promo code id as promo rule id.
* Restricted to UTF-8 characters with max length 50
*/
protected $id;
/**
* @var string
* @title Title
* @default null
* @description The title that will show up in promotion campaign. Restricted to UTF-8 characters with max length 100
*/
protected $title;
/**
* @var string
* @title Description
* @default null
* @description The description of a promotion
*/
protected $description;
/**
* @var \DateTime
* @title Start Time
* @default null
* @description The date and time when the promotion starts in ISO 8601 format
*/
protected $starts_at;
/**
* @var \DateTime
* @title Start Time
* @default null
* @description The date and time when the promotion starts in ISO 8601 format
*/
protected $ends_at;
/**
* @var float
* @title Amount
* @required
* @description The amount of discount; Positive dollar or percentage amount.
*/
protected $amount;
/**
* @var string
* @title Type
* @required
* @description One of fixed , percentage
*/
protected $type;
/**
* @var string
* @title Target
* @required
* @description One of per_item, total, shipping
*/
protected $target;
/**
* @var boolean
* @title Enabled
* @default true
* @description Whether the promo rule is currently enabled
*/
protected $enabled = true;
/**
* @var \DateTime
* @title Start Time
* @default null
* @description The date and time when the promotion starts in ISO 8601 format
*/
protected $created_at_foreign;
/**
* @var \DateTime
* @title Start Time
* @default null
* @description The date and time when the promotion starts in ISO 8601 format
*/
protected $updated_at_foreign;
/**
* @return array
*/
public function getValidation()
{
return [
'id' => 'required',
'amount' => 'required|number',
'type' => 'required',
'target' => 'required',
'enabled' => 'boolean',
'starts_at' => 'date',
'ends_at' => 'date',
'created_at_foreign' => 'date',
'updated_at_foreign' => 'date',
];
}
/**
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* @param null $id
* @return MailChimp_WooCommerce_PromoRule
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* @param string $name
* @return MailChimp_WooCommerce_PromoRule
*/
public function setTitle($name)
{
$this->title = $name;
return $this;
}
/**
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* @param string $description
* @return MailChimp_WooCommerce_PromoRule
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* @param \DateTime $date
* @return $this
*/
public function setStartsAt(\DateTime $date)
{
$this->starts_at = (string) $date;
return $this;
}
/**
* @return \DateTime
*/
public function getStartsAt()
{
return $this->starts_at;
}
/**
* @param \DateTime $date
* @return $this
*/
public function setEndsAt(\DateTime $date)
{
$this->ends_at = (string) $date;
return $this;
}
/**
* @return \DateTime
*/
public function getEndsAt()
{
return $this->ends_at;
}
/**
* @param $enabled
* @return $this
*/
public function setEnabled($enabled)
{
$this->enabled = (bool) $enabled;
return $this;
}
/**
* @return bool
*/
public function isEnabled()
{
return (bool) $this->enabled;
}
/**
* @return string
*/
public function getAmount()
{
return $this->amount;
}
/**
* @param int $amount
* @return MailChimp_WooCommerce_PromoRule
*/
public function setAmount($amount)
{
$this->amount = $amount;
return $this;
}
/**
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* @return string
*/
public function getTarget()
{
return $this->target;
}
/**
* @return $this
*/
public function setTypeFixed()
{
$this->type = 'fixed';
return $this;
}
/**
* @return $this
*/
public function setTypePercentage()
{
$this->type = 'percentage';
return $this;
}
/**
* @return $this
*/
public function setTargetTypePerItem()
{
$this->target = 'per_item';
return $this;
}
/**
* @return $this
*/
public function setTargetTypeShipping()
{
$this->target = 'shipping';
return $this;
}
/**
* @return $this
*/
public function setTargetTypeTotal()
{
$this->target = 'total';
return $this;
}
/**
* @param \DateTime $time
* @return $this
*/
public function setUpdatedAt(\DateTime $time)
{
$this->updated_at_foreign = (string) $time;
return $this;
}
/**
* @return null
*/
public function getUpdatedAt()
{
return $this->updated_at_foreign;
}
/**
* @param \DateTime $time
* @return $this
*/
public function setCreatedAt(\DateTime $time)
{
$this->created_at_foreign = (string) $time;
return $this;
}
/**
* @return null
*/
public function getCreatedAt()
{
return $this->created_at_foreign;
}
/**
* @return array
*/
public function toArray()
{
return mailchimp_array_remove_empty([
'id' => (string) $this->getId(),
'title' => (string) $this->getTitle(),
'description' => (string) $this->getDescription(),
'starts_at' => (string) $this->getStartsAt(),
'ends_at' => (string) $this->getEndsAt(),
'amount' => floatval($this->getAmount()),
'type' => (string) $this->getType(),
'target' => (string) $this->getTarget(),
'enabled' => (bool) $this->isEnabled(),
'created_at_foreign' => (string) $this->getCreatedAt(),
'updated_at_foreign' => (string) $this->getUpdatedAt(),
]);
}
/**
* @param array $data
* @return MailChimp_WooCommerce_PromoRule
*/
public function fromArray(array $data)
{
$singles = [
'id',
'title',
'description',
'starts_at',
'ends_at',
'amount',
'type',
'target',
'enabled',
'created_at_foreign',
'updated_at_foreign'
];
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
return $this;
}
}

View File

@@ -0,0 +1,390 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 3/8/16
* Time: 3:13 PM
*/
class MailChimp_WooCommerce_Store
{
protected $id = null;
protected $is_syncing = false;
protected $list_id = null;
protected $name = null;
protected $domain = null;
protected $email_address = null;
protected $currency_code = null;
protected $money_format = null;
protected $primary_locale = null;
protected $timezone = null;
protected $phone = null;
protected $address = null;
protected $platform = null;
protected $connected_site = null;
/**
* @return array
*/
public function getValidation()
{
return array(
'id' => 'required|string',
'list_id' => 'required|string',
'name' => 'required|string',
'domain' => 'string',
'email_address' => 'email',
'currency_code' => 'required|currency_code',
'primary_locale' => 'locale_basic',
'timezone' => 'timezone',
'phone' => 'string',
);
}
/**
* @return null
*/
public function getId()
{
return $this->id;
}
/**
* @param null $id
* @return MailChimp_WooCommerce_Store
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @param $bool
* @return $this
*/
public function flagSyncing($bool)
{
$this->is_syncing = $bool;
return $this;
}
/**
* @return bool
*/
public function isSyncing()
{
return $this->is_syncing;
}
/**
* @return null
*/
public function getListId()
{
return $this->list_id;
}
/**
* @param null $list_id
* @return MailChimp_WooCommerce_Store
*/
public function setListId($list_id)
{
$this->list_id = $list_id;
return $this;
}
/**
* @return null
*/
public function getName()
{
return $this->name;
}
/**
* @param null $name
* @return MailChimp_WooCommerce_Store;
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* @return null
*/
public function getDomain()
{
return $this->domain;
}
/**
* @param null $domain
* @return MailChimp_WooCommerce_Store;
*/
public function setDomain($domain)
{
$this->domain = $domain;
return $this;
}
/**
* @return null
*/
public function getEmailAddress()
{
return $this->email_address;
}
/**
* @param null $email_address
* @return MailChimp_WooCommerce_Store;
*/
public function setEmailAddress($email_address)
{
$this->email_address = $email_address;
return $this;
}
/**
* @return null
*/
public function getCurrencyCode()
{
return $this->currency_code;
}
/**
* @param null $currency_code
* @return MailChimp_WooCommerce_Store;
*/
public function setCurrencyCode($currency_code)
{
$this->currency_code = $currency_code;
return $this;
}
/**
* @return null
*/
public function getMoneyFormat()
{
return $this->money_format;
}
/**
* @param null $money_format
* @return MailChimp_WooCommerce_Store;
*/
public function setMoneyFormat($money_format)
{
$this->money_format = $money_format;
return $this;
}
/**
* @return null
*/
public function getPrimaryLocale()
{
return $this->primary_locale;
}
/**
* @param null $primary_locale
* @return MailChimp_WooCommerce_Store;
*/
public function setPrimaryLocale($primary_locale)
{
$this->primary_locale = $primary_locale;
return $this;
}
/**
* @return null
*/
public function getTimezone()
{
return $this->timezone;
}
/**
* @param null $timezone
* @return MailChimp_WooCommerce_Store;
*/
public function setTimezone($timezone)
{
$this->timezone = $timezone;
return $this;
}
/**
* @return null
*/
public function getPhone()
{
return $this->phone;
}
/**
* @param null $phone
* @return MailChimp_WooCommerce_Store;
*/
public function setPhone($phone)
{
$this->phone = $phone;
return $this;
}
/**
* @param $platform
* @return $this
*/
public function setPlatform($platform)
{
$this->platform = $platform;
return $this;
}
/**
* @return string
*/
public function getPlatform()
{
return $this->platform;
}
/**
* @return MailChimp_WooCommerce_Address
*/
public function getAddress()
{
if (empty($this->address)) {
$this->address = new MailChimp_WooCommerce_Address();
}
return $this->address;
}
/**
* @param MailChimp_WooCommerce_Address $address
* @return Store;
*/
public function setAddress(MailChimp_WooCommerce_Address $address)
{
$this->address = $address;
return $this;
}
/**
* @return null|string
*/
public function getConnectedSiteForeignID()
{
return $this->getConnectedSiteParam('site_foreign_id');
}
/**
* @return null|string
*/
public function getConnectedSiteScriptUrl()
{
if (($script = $this->getConnectedSiteParam('site_script'))) {
return $script['url'];
}
return false;
}
/**
* @return null|string
*/
public function getConnectedSiteScriptFragment()
{
if (($script = $this->getConnectedSiteParam('site_script'))) {
return $script['fragment'];
}
return false;
}
/**
* @param $key
* @param null $default
* @return null
*/
public function getConnectedSiteParam($key, $default = null)
{
if (empty($this->connected_site)) {
return $default;
}
return array_key_exists($key, $this->connected_site) ? $this->connected_site[$key] : null;
}
/**
* @return array
*/
public function toArray()
{
return mailchimp_array_remove_empty(array(
'id' => $this->getId(),
'is_syncing' => $this->isSyncing(),
'platform' => $this->getPlatform(),
'list_id' => $this->getListId(),
'name' => $this->getName(),
'domain' => $this->getDomain(),
'email_address' => $this->getEmailAddress(),
'currency_code' => $this->getCurrencyCode(),
'money_format' => $this->getMoneyFormat(),
'primary_locale' => $this->getPrimaryLocale(),
'timezone' => $this->getTimezone(),
'phone' => $this->getPhone(),
'address' => $this->getAddress()->toArray(),
));
}
/**
* @param array $data
* @return MailChimp_WooCommerce_Store
*/
public function fromArray(array $data)
{
$singles = array(
'id', 'list_id', 'name', 'domain', 'is_syncing',
'email_address', 'currency_code', 'money_format',
'primary_locale', 'timezone', 'phone', 'platform',
);
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
if (array_key_exists('address', $data)) {
$address = new MailChimp_WooCommerce_Address();
$this->address = $address->fromArray($data['address']);
}
if (array_key_exists('connected_site', $data)) {
$this->connected_site = $data['connected_site'];
}
return $this;
}
}

View File

@@ -0,0 +1,101 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/13/16
* Time: 2:32 PM
*/
class MailChimp_WooCommerce_Api
{
protected static $filterable_actions = array(
'paginate-resource',
);
/**
* @param int $default_page
* @param int $default_per
* @return array
*/
public static function filter($default_page = null, $default_per = null)
{
if (isset($_GET['mailchimp-woocommerce']) && isset($_GET['mailchimp-woocommerce']['action'])) {
if (in_array($_GET['mailchimp-woocommerce']['action'], static::$filterable_actions)) {
if (empty($default_page)) {
$page = isset($_GET['page']) ? (int) $_GET['page'] : null;
}
if (empty($default_per)) {
$per = isset($_GET['per']) ? (int) $_GET['per'] : null;
}
}
}
if (empty($page)) $page = 1;
if (empty($per)) $per = 5;
return array($page, $per);
}
/**
* @param null $page
* @param null $per
* @return object|stdClass
*/
public function paginateProducts($page = null, $per = null)
{
return $this->paginate('products', $page, $per);
}
/**
* @param null $page
* @param null $per
* @return object|stdClass
*/
public function paginateOrders($page = null, $per = null)
{
return $this->paginate('orders', $page, $per);
}
/**
* @param $resource
* @param int $page
* @param int $per
* @return object|stdClass
*/
public function paginate($resource, $page = 1, $per = 5)
{
if (($sync = $this->engine($resource))) {
return $sync->compile($page, $per);
}
return (object) array(
'endpoint' => $resource,
'page' => $page,
'count' => 0,
'stuffed' => false,
'items' => array(),
);
}
/**
* @param $resource
* @return bool|MailChimp_WooCommerce_Transform_Orders|MailChimp_WooCommerce_Transform_Products|MailChimp_WooCommerce_Transform_Coupons
*/
public function engine($resource)
{
switch ($resource) {
case 'products' :
return new MailChimp_WooCommerce_Transform_Products();
break;
case 'orders' :
return new MailChimp_WooCommerce_Transform_Orders();
break;
case 'coupons':
return new MailChimp_WooCommerce_Transform_Coupons();
default:
return false;
}
}
}

View File

@@ -0,0 +1,162 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/8/16
* Time: 4:16 PM
*/
class MailChimp_WooCommerce_CreateListSubmission
{
/**
* @var array
*/
protected $props = array();
/**
* @param $name
* @return $this
*/
public function setName($name)
{
$this->props['name'] = $name;
return $this;
}
/**
* @param $bool
* @return $this
*/
public function setUseArchiveBar($bool)
{
$this->props['use_archive_bar'] = (bool) $bool;
return $this;
}
/**
* @param $reminder
* @return $this
*/
public function setPermissionReminder($reminder)
{
$this->props['permission_reminder'] = $reminder;
return $this;
}
/**
* @param $email
* @return $this
*/
public function setNotifyOnSubscribe($email)
{
$this->props['notify_on_subscribe'] = $email;
return $this;
}
/**
* @param string $email
* @return $this
*/
public function setNotifyOnUnSubscribe($email)
{
$this->props['notify_on_unsubscribe'] = $email;
return $this;
}
/**
* @param $bool
* @return $this
*/
public function setEmailTypeOption($bool)
{
$this->props['email_type_option'] = (bool) $bool;
return $this;
}
/**
* @param bool $public
* @return $this
*/
public function setVisibility($public = true)
{
$this->props['visibility'] = $public ? 'pub' : 'prv';
return $this;
}
/**
* @param $name
* @param $email
* @param $subject
* @param string $language
* @return $this
*/
public function setCampaignDefaults($name, $email, $subject, $language = 'en')
{
$this->props['campaign_defaults'] = array(
'from_name' => $name,
'from_email' => $email,
'subject' => $subject,
'language' => $language,
);
return $this;
}
/**
* @param MailChimp_WooCommerce_Address $address
* @return $this
*/
public function setContact(MailChimp_WooCommerce_Address $address)
{
$data = array();
if (($company = $address->getCompany()) && !empty($company)) {
$data['company'] = $company;
}
if (($street = $address->getAddress1()) && !empty($address)) {
$data['address1'] = $street;
}
if (($city = $address->getCity()) && !empty($city)) {
$data['city'] = $city;
}
if (($state = $address->getProvince()) && !empty($state)) {
$data['state'] = $state;
}
if (($zip = $address->getPostalCode()) && !empty($zip)) {
$data['zip'] = $zip;
}
if (($country = $address->getCountry()) && !empty($country)) {
$data['country'] = $country;
}
if (($phone = $address->getPhone()) && !empty($phone)) {
$data['phone'] = $phone;
}
$this->props['contact'] = $data;
return $this;
}
/**
* @return array
*/
public function getSubmission()
{
return $this->props;
}
}

View File

@@ -0,0 +1,136 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 10/06/17
* Time: 8:29 AM
*/
class MailChimp_WooCommerce_Transform_Coupons
{
/**
* @param int $page
* @param int $limit
* @return \stdClass
*/
public function compile($page = 1, $limit = 5)
{
$response = (object) array(
'endpoint' => 'coupons',
'page' => $page ? $page : 1,
'limit' => (int) $limit,
'count' => 0,
'stuffed' => false,
'items' => array(),
);
if ((($coupons = $this->getCouponPosts($page, $limit)) && !empty($coupons))) {
foreach ($coupons as $post) {
$response->items[] = $this->transform($post->ID);
$response->count++;
}
}
$response->stuffed = ($response->count > 0 && (int) $response->count === (int) $limit) ? true : false;
return $response;
}
/**
* @param int $post_id
* @return MailChimp_WooCommerce_PromoCode
*/
public function transform($post_id)
{
$resource = new WC_Coupon($post_id);
$valid = true;
if (($exp = $resource->get_date_expires()) && current_time('timestamp', true) > $exp->getTimestamp()) {
$valid = false;
}
$rule = new MailChimp_WooCommerce_PromoRule();
$rule->setId($resource->get_id());
$rule->setTitle($resource->get_code());
$rule->setDescription($resource->get_description());
$rule->setEnabled($valid);
$rule->setAmount($resource->get_amount('edit'));
if (!$rule->getDescription()) {
$rule->setDescription($resource->get_code());
}
switch ($resource->get_discount_type()) {
case 'fixed_product':
$rule->setTypeFixed();
$rule->setTargetTypePerItem();
break;
case 'fixed_cart':
$rule->setTypeFixed();
$rule->setTargetTypeTotal();
break;
case 'percent':
$rule->setTypePercentage();
$rule->setTargetTypeTotal();
$rule->setAmount(($resource->get_amount('edit')/100));
break;
}
if (($exp = $resource->get_date_expires())) {
$rule->setEndsAt($exp);
}
$code = new MailChimp_WooCommerce_PromoCode();
$code->setId($resource->get_id());
$code->setCode($resource->get_code());
$code->setEnabled($valid);
$code->setRedemptionURL(get_home_url());
$code->setUsageCount($resource->get_usage_count());
// attach the rule for use.
$code->attachPromoRule($rule);
return $code;
}
/**
* @param int $page
* @param int $posts
* @return array|bool
*/
public function getCouponPosts($page = 1, $posts = 5)
{
$coupons = get_posts(array(
'post_type' => array_merge(array_keys(wc_get_product_types()), array('shop_coupon')),
'posts_per_page' => $posts,
'paged' => $page,
'orderby' => 'ID',
'order' => 'ASC',
));
if (empty($coupons)) {
sleep(2);
$coupons = get_posts(array(
'post_type' => array_merge(array_keys(wc_get_product_types()), array('shop_coupon')),
'posts_per_page' => $posts,
'paged' => $page,
'orderby' => 'ID',
'order' => 'ASC',
));
if (empty($coupons)) {
return false;
}
}
return $coupons;
}
}

View File

@@ -0,0 +1,381 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/13/16
* Time: 8:29 AM
*/
class MailChimp_WooCommerce_Transform_Orders
{
public $campaign_id = null;
/**
* @param int $page
* @param int $limit
* @return \stdClass
*/
public function compile($page = 1, $limit = 5)
{
$response = (object) array(
'endpoint' => 'orders',
'page' => $page ? $page : 1,
'limit' => (int) $limit,
'count' => 0,
'valid' => 0,
'drafts' => 0,
'stuffed' => false,
'items' => array(),
);
if ((($orders = $this->getOrderPosts($page, $limit)) && !empty($orders))) {
foreach ($orders as $post) {
$response->count++;
if ($post->post_status === 'auto-draft') {
$response->drafts++;
continue;
}
$order = $this->transform($post);
if (!$order->isFlaggedAsAmazonOrder()) {
$response->valid++;
$response->items[] = $order;
}
}
}
$response->stuffed = ($response->count > 0 && (int) $response->count === (int) $limit) ? true : false;
return $response;
}
/**
* @param WP_Post $post
* @return MailChimp_WooCommerce_Order
*/
public function transform(WP_Post $post)
{
$woo = new WC_Order($post);
$order = new MailChimp_WooCommerce_Order();
// just skip these altogether because we can't submit any amazon orders anyway.
if (mailchimp_string_contains($woo->get_billing_email(), '@marketplace.amazon.com')) {
return $order->flagAsAmazonOrder(true);
}
$order->setId($woo->get_order_number());
// if we have a campaign id let's set it now.
if (!empty($this->campaign_id)) {
$order->setCampaignId($this->campaign_id);
}
$order->setProcessedAt($woo->get_date_created()->setTimezone(new \DateTimeZone('UTC')));
$order->setCurrencyCode($woo->get_currency());
// grab the current statuses - this will end up being custom at some point.
$statuses = $this->getOrderStatuses();
// grab the order status
$status = $woo->get_status();
// map the fulfillment and financial statuses based on the map above.
$fulfillment_status = array_key_exists($status, $statuses) ? $statuses[$status]->fulfillment : null;
$financial_status = array_key_exists($status, $statuses) ? $statuses[$status]->financial : $status;
// set the fulfillment_status
$order->setFulfillmentStatus($fulfillment_status);
// set the financial status
$order->setFinancialStatus($financial_status);
// if the status is processing, we need to send this one first, then send a 'paid' status right after.
if ($status === 'processing') {
$order->confirmAndPay(true);
}
// only set this if the order is cancelled.
if ($status === 'cancelled') {
$order->setCancelledAt($woo->get_date_modified()->setTimezone(new \DateTimeZone('UTC')));
}
// set the total
$order->setOrderTotal($woo->get_total());
// set the order URL
$order->setOrderURL($woo->get_view_order_url());
// if we have any tax
$order->setTaxTotal($woo->get_total_tax());
// if we have shipping.
$order->setShippingTotal($woo->get_shipping_total());
// set the order discount
$order->setDiscountTotal($woo->get_total_discount());
// set the customer
$order->setCustomer($this->buildCustomerFromOrder($woo));
// apply the addresses to the order
$order->setShippingAddress($this->transformShippingAddress($woo));
$order->setBillingAddress($this->transformBillingAddress($woo));
// loop through all the order items
foreach ($woo->get_items() as $key => $order_detail) {
/** @var WC_Order_Item_Product $order_detail */
// add it into the order item container.
$item = $this->transformLineItem($key, $order_detail);
// if we don't have a product post with this id, we need to add a deleted product to the MC side
if (!($product = $order_detail->get_product()) || 'trash' === $product->get_status()) {
$pid = $order_detail->get_product_id();
// check if it exists, otherwise create a new one.
if (($deleted_product = MailChimp_WooCommerce_Transform_Products::deleted($pid))) {
// swap out the old item id and product variant id with the deleted version.
$item->setProductId("deleted_{$pid}");
$item->setProductVariantId("deleted_{$pid}");
// add the item and continue on the loop.
$order->addItem($item);
continue;
}
mailchimp_log('order.items.error', "Order #{$woo->get_id()} :: Product {$pid} does not exist!");
continue;
}
$order->addItem($item);
}
//if (($refund = $woo->get_total_refunded()) && $refund > 0){
// this is where we would be altering the submission to tell us about the refund.
//}
return $order;
}
/**
* @param WC_Order $order
* @return MailChimp_WooCommerce_Customer
*/
public function buildCustomerFromOrder(WC_Order $order)
{
$customer = new MailChimp_WooCommerce_Customer();
$customer->setId(md5(trim(strtolower($order->get_billing_email()))));
$customer->setCompany($order->get_billing_company());
$customer->setEmailAddress(trim($order->get_billing_email()));
$customer->setFirstName($order->get_billing_first_name());
$customer->setLastName($order->get_billing_last_name());
$customer->setAddress($this->transformBillingAddress($order));
if (!($stats = $this->getCustomerOrderTotals($order->get_user_id()))) {
$stats = (object) array('count' => 0, 'total' => 0);
}
$customer->setOrdersCount($stats->count);
$customer->setTotalSpent($stats->total);
// we are saving the post meta for subscribers on each order... so if they have subscribed on checkout
$subscriber_meta = get_post_meta($order->get_id(), 'mailchimp_woocommerce_is_subscribed', true);
$subscribed_on_order = $subscriber_meta === '' ? false : (bool) $subscriber_meta;
$customer->setOptInStatus($subscribed_on_order);
// if they didn't subscribe on the order, we need to check to make sure they're not already a subscriber
// if they are, we just need to make sure that we don't unsubscribe them just because they unchecked this box.
if (!$subscribed_on_order) {
try {
$subscriber = mailchimp_get_api()->member(mailchimp_get_list_id(), $customer->getEmailAddress());
$status = !in_array($subscriber['status'], array('unsubscribed', 'transactional'));
$customer->setOptInStatus($status);
} catch (\Exception $e) {}
}
return $customer;
}
/**
* @param $key
* @param WC_Order_Item_Product $order_detail
* @return MailChimp_WooCommerce_LineItem
*/
protected function transformLineItem($key, $order_detail)
{
// fire up a new MC line item
$item = new MailChimp_WooCommerce_LineItem();
$item->setId($key);
$item->setPrice($order_detail->get_total());
$item->setProductId($order_detail->get_product_id());
$variation_id = $order_detail->get_variation_id();
if (empty($variation_id)) $variation_id = $order_detail->get_product_id();
$item->setProductVariantId($variation_id);
$item->setQuantity($order_detail->get_quantity());
if ($item->getQuantity() > 1) {
$current_price = $item->getPrice();
$price = ($current_price/$item->getQuantity());
$item->setPrice($price);
}
return $item;
}
/**
* @param WC_Order $order
* @return MailChimp_WooCommerce_Address
*/
public function transformBillingAddress(WC_Order $order)
{
// use the info from the order to compile an address.
$address = new MailChimp_WooCommerce_Address();
$address->setAddress1($order->get_billing_address_1());
$address->setAddress2($order->get_billing_address_2());
$address->setCity($order->get_billing_city());
$address->setProvince($order->get_billing_state());
$address->setPostalCode($order->get_billing_postcode());
$address->setCountry($order->get_billing_country());
$address->setPhone($order->get_billing_phone());
$bfn = $order->get_billing_first_name();
$bln = $order->get_billing_last_name();
// if we have billing names set it here
if (!empty($bfn) && !empty($bln)) {
$address->setName("{$bfn} {$bln}");
}
return $address;
}
/**
* @param WC_Order $order
* @return MailChimp_WooCommerce_Address
*/
public function transformShippingAddress(WC_Order $order)
{
$address = new MailChimp_WooCommerce_Address();
$address->setAddress1($order->get_shipping_address_1());
$address->setAddress2($order->get_shipping_address_2());
$address->setCity($order->get_shipping_city());
$address->setProvince($order->get_shipping_state());
$address->setPostalCode($order->get_shipping_postcode());
$address->setCountry($order->get_shipping_country());
// shipping does not have a phone number, so maybe use this?
$address->setPhone($order->get_billing_phone());
$sfn = $order->get_shipping_first_name();
$sln = $order->get_shipping_last_name();
// if we have billing names set it here
if (!empty($sfn) && !empty($sln)) {
$address->setName("{$sfn} {$sln}");
}
return $address;
}
/**
* @param int $page
* @param int $posts
* @return array|bool
*/
public function getOrderPosts($page = 1, $posts = 5)
{
$params = array(
'post_type' => wc_get_order_types(),
'post_status' => array_keys(wc_get_order_statuses()),
'posts_per_page' => $posts,
'paged' => $page,
'orderby' => 'id',
'order' => 'ASC',
);
$orders = get_posts($params);
if (empty($orders)) {
sleep(2);
$orders = get_posts($params);
}
return empty($orders) ? false : $orders;
}
/**
* returns an object with a 'total' and a 'count'.
*
* @param $user_id
* @return object
*/
public function getCustomerOrderTotals($user_id)
{
$customer = new WC_Customer($user_id);
$customer->get_order_count();
$customer->get_total_spent();
return (object) array(
'count' => $customer->get_order_count(),
'total' => $customer->get_total_spent()
);
}
/**
* "Pending payment" in the UI fires the order confirmation email MailChimp
* "Completed” in the UI fires the MailChimp Order Invoice
* "Cancelled" does what we think it does
*
* @return array
*/
public function getOrderStatuses()
{
return array(
// Order received (unpaid)
'pending' => (object) array(
'financial' => 'pending',
'fulfillment' => null
),
// Payment received and stock has been reduced the order is awaiting fulfillment.
// All product orders require processing, except those for digital downloads
'processing' => (object) array(
'financial' => 'pending',
'fulfillment' => null
),
// Awaiting payment stock is reduced, but you need to confirm payment
'on-hold' => (object) array(
'financial' => 'on-hold',
'fulfillment' => null
),
// Order fulfilled and complete requires no further action
'completed' => (object) array(
'financial' => 'fulfilled',
'fulfillment' => 'fulfilled'
),
// Cancelled by an admin or the customer no further action required
'cancelled' => (object) array(
'financial' => 'cancelled',
'fulfillment' => null
),
// Refunded by an admin no further action required
'refunded' => (object) array(
'financial' => 'refunded',
'fulfillment' => null
),
// Payment failed or was declined (unpaid). Note that this status may not show immediately and
// instead show as Pending until verified (i.e., PayPal)
'failed' => (object) array(
'financial' => 'failed',
'fulfillment' => null
),
);
}
}

View File

@@ -0,0 +1,536 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@mailchimp.com
* Date: 7/13/16
* Time: 8:29 AM
*/
class MailChimp_WooCommerce_Transform_Orders
{
public $campaign_id = null;
protected $use_user_address = false;
/**
* @param int $page
* @param int $limit
* @return \stdClass
*/
public function compile($page = 1, $limit = 5)
{
$response = (object) array(
'endpoint' => 'orders',
'page' => $page ? $page : 1,
'limit' => (int) $limit,
'count' => 0,
'valid' => 0,
'drafts' => 0,
'stuffed' => false,
'items' => array(),
);
if ((($orders = $this->getOrderPosts($page, $limit)) && !empty($orders))) {
foreach ($orders as $post) {
$response->count++;
if ($post->post_status === 'auto-draft') {
$response->drafts++;
continue;
}
$order = $this->transform($post);
if (!$order->isFlaggedAsAmazonOrder()) {
$response->valid++;
$response->items[] = $order;
}
}
}
$response->stuffed = ($response->count > 0 && (int) $response->count === (int) $limit) ? true : false;
return $response;
}
/**
* @param WC_Order $woo
* @return array
*/
protected function dates(WC_Order $woo)
{
if (method_exists($woo, 'get_date_modified')) {
$created_at = $woo->get_date_modified();
$updated_at = $woo->get_date_modified();
} elseif (property_exists($woo, 'order_date') && property_exists($woo, 'modified_date')) {
$created_at = $woo->order_date ? new \DateTime($woo->order_date) : null;
$updated_at = $woo->modified_date ? new \DateTime($woo->modified_date) : null;
} else {
$created_at = $updated_at = new \DateTime();
}
return array($created_at, $updated_at);
}
/**
* @param WP_Post $post
* @return MailChimp_WooCommerce_Order
*/
public function transform(WP_Post $post)
{
$woo = new WC_Order($post);
$order = new MailChimp_WooCommerce_Order();
$order->setId($woo->get_order_number());
// just skip these altogether because we can't submit any amazon orders anyway.
if (mailchimp_string_contains($woo->billing_email, '@marketplace.amazon.com')) {
return $order->flagAsAmazonOrder(true);
}
// if we have a campaign id let's set it now.
if (!empty($this->campaign_id)) {
$order->setCampaignId($this->campaign_id);
}
$order->setProcessedAt($woo->get_date_created()->setTimezone(new \DateTimeZone('UTC')));
$order->setCurrencyCode($woo->get_currency());
// grab the current statuses - this will end up being custom at some point.
$statuses = $this->getOrderStatuses();
// grab the order status
$status = $woo->get_status();
// map the fulfillment and financial statuses based on the map above.
$fulfillment_status = array_key_exists($status, $statuses) ? $statuses[$status]->fulfillment : null;
$financial_status = array_key_exists($status, $statuses) ? $statuses[$status]->financial : $status;
// set the fulfillment_status
$order->setFulfillmentStatus($fulfillment_status);
// set the financial status
$order->setFinancialStatus($financial_status);
// if the status is processing, we need to send this one first, then send a 'paid' status right after.
if ($status === 'processing') {
$order->confirmAndPay(true);
}
// only set this if the order is cancelled.
if ($status === 'cancelled') {
$order->setCancelledAt($woo->get_date_modified()->setTimezone(new \DateTimeZone('UTC')));
}
// set the total
$order->setOrderTotal($woo->get_total());
// set the order URL
$order->setOrderURL($woo->get_view_order_url());
// if we have any tax
$order->setTaxTotal($woo->get_total_tax());
// if we have shipping.
$order->setShippingTotal($woo->get_total_shipping());
// set the order discount
$order->setDiscountTotal($woo->get_total_discount());
// set the customer
$order->setCustomer($this->buildCustomerFromOrder($woo));
// apply the addresses to the order
$addresses = $this->getOrderAddresses($woo);
$order->setShippingAddress($addresses->shipping);
$order->setBillingAddress($addresses->billing);
// loop through all the order items
foreach ($woo->get_items() as $key => $order_detail) {
// add it into the order item container.
$item = $this->buildLineItem($key, $order_detail);
// if we don't have a product post with this id, we need to add a deleted product to the MC side
if (!($product_post = get_post($item->getProductId()))) {
// check if it exists, otherwise create a new one.
if (($deleted_product = MailChimp_WooCommerce_Transform_Products::deleted($item->getProductId()))) {
$deleted_product_id = "deleted_{$item->getProductId()}";
// swap out the old item id and product variant id with the deleted version.
$item->setProductId($deleted_product_id);
$item->setProductVariantId($deleted_product_id);
// add the item and continue on the loop.
$order->addItem($item);
continue;
}
mailchimp_log('order.items.error', "Order #{$woo->get_order_number()} :: Product {$item->getProductId()} does not exist!");
continue;
}
$order->addItem($item);
}
// apply the coupon discounts
if (function_exists('wc_get_coupon_id_by_code') && ($used_coupons = $woo->get_used_coupons()) && is_array($used_coupons)) {
foreach ($used_coupons as $coupon_code) {
if (($coupon_id = wc_get_coupon_id_by_code($coupon_code))) {
$coupon = new WC_Coupon($coupon_id);
$is_percentage = $coupon->get_discount_type() === 'percent';
$order->addDiscount($coupon_code, $coupon->get_amount('edit'), $is_percentage);
}
}
}
//if (($refund = $woo->get_total_refunded()) && $refund > 0){
// this is where we would be altering the submission to tell us about the refund.
//}
return $order;
}
/**
* @param WC_Order $order
* @return MailChimp_WooCommerce_Customer
*/
public function buildCustomerFromOrder(WC_Order $order)
{
$customer = new MailChimp_WooCommerce_Customer();
$customer->setId(md5(trim(strtolower($order->billing_email))));
$customer->setCompany($order->billing_company);
$customer->setEmailAddress(trim($order->billing_email));
$customer->setFirstName($order->billing_first_name);
$customer->setLastName($order->billing_last_name);
$customer->setOrdersCount(1);
$customer->setTotalSpent($order->get_total());
// we are saving the post meta for subscribers on each order... so if they have subscribed on checkout
$subscriber_meta = get_post_meta($order->get_id(), 'mailchimp_woocommerce_is_subscribed', true);
$subscribed_on_order = $subscriber_meta === '' ? false : (bool) $subscriber_meta;
$customer->setOptInStatus($subscribed_on_order);
// if they didn't subscribe on the order, we need to check to make sure they're not already a subscriber
// if they are, we just need to make sure that we don't unsubscribe them just because they unchecked this box.
if (!$subscribed_on_order) {
try {
$subscriber = mailchimp_get_api()->member(mailchimp_get_list_id(), $customer->getEmailAddress());
$status = !in_array($subscriber['status'], array('unsubscribed', 'transactional'));
$customer->setOptInStatus($status);
} catch (\Exception $e) {}
}
// use the info from the order to compile an address.
$address = new MailChimp_WooCommerce_Address();
$address->setAddress1($order->billing_address_1);
$address->setAddress2($order->billing_address_2);
$address->setCity($order->billing_city);
$address->setProvince($order->billing_state);
$address->setPostalCode($order->billing_postcode);
$address->setCountry($order->billing_country);
$address->setPhone($order->billing_phone);
// if we have billing names set it here
if (!empty($order->billing_first_name) && !empty($order->billing_last_name)) {
$address->setName($order->billing_first_name.' '.$order->billing_last_name);
}
$customer->setAddress($address);
if (($user = get_userdata($order->customer_user))) {
/**
* IF we wanted to use the user data instead we would do it here.
* but we discussed using the billing address instead.
*/
if ($this->use_user_address) {
$customer->setId($user->ID);
$customer->setEmailAddress($user->user_email);
$customer->setFirstName($user->first_name);
$customer->setLastName($user->last_name);
if (($address = $this->getUserAddress($user->ID))) {
if (count($address->toArray()) > 3) {
$customer->setAddress($address);
}
}
}
if (!($stats = $this->getCustomerOrderTotals($order->customer_user))) {
$stats = (object) array('count' => 0, 'total' => 0);
}
$customer->setOrdersCount($stats->count);
$customer->setTotalSpent($stats->total);
}
return $customer;
}
/**
* @param $key
* @param $order_detail
* @return MailChimp_WooCommerce_LineItem
*/
protected function buildLineItem($key, $order_detail)
{
// fire up a new MC line item
$item = new MailChimp_WooCommerce_LineItem();
$item->setId($key);
if (isset($order_detail['item_meta']) && is_array($order_detail['item_meta'])) {
foreach ($order_detail['item_meta'] as $meta_key => $meta_data_array) {
if (!isset($meta_data_array[0])) {
continue;
}
switch ($meta_key) {
case '_line_subtotal':
$item->setPrice($meta_data_array[0]);
break;
case '_product_id':
$item->setProductId($meta_data_array[0]);
break;
case '_variation_id':
$item->setProductVariantId($meta_data_array[0]);
break;
case '_qty':
$item->setQuantity($meta_data_array[0]);
break;
}
}
if ($item->getProductVariantId() <= 0) {
$item->setProductVariantId($item->getProductId());
}
} elseif (isset($order_detail['item_meta_array']) && is_array($order_detail['item_meta_array'])) {
/// Some users have the newer version of the item meta.
foreach ($order_detail['item_meta_array'] as $meta_id => $object) {
if (!isset($object->key)) {
continue;
}
switch ($object->key) {
case '_line_subtotal':
$item->setPrice($object->value);
break;
case '_product_id':
$item->setProductId($object->value);
break;
case '_variation_id':
$item->setProductVariantId($object->value);
break;
case '_qty':
$item->setQuantity($object->value);
break;
}
}
if ($item->getProductVariantId() <= 0) {
$item->setProductVariantId($item->getProductId());
}
}
if ($item->getQuantity() > 1) {
$current_price = $item->getPrice();
$price = ($current_price/$item->getQuantity());
$item->setPrice($price);
}
return $item;
}
/**
* @param int $page
* @param int $posts
* @return array|bool
*/
public function getOrderPosts($page = 1, $posts = 5)
{
$params = array(
'post_type' => 'shop_order',
'posts_per_page' => $posts,
'paged' => $page,
'orderby' => 'id',
'order' => 'ASC',
);
$orders = get_posts($params);
if (empty($orders)) {
sleep(2);
$orders = get_posts($params);
}
return empty($orders) ? false : $orders;
}
/**
* returns an object with a 'total' and a 'count'.
*
* @param $user_id
* @return object
*/
public function getCustomerOrderTotals($user_id)
{
$stats = (object) array('count' => 0, 'total' => 0);
if (!empty($user_id)) {
$orders = get_posts(apply_filters('woocommerce_my_account_my_orders_query', array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => $user_id,
'post_type' => 'shop_order',
'post_status' => 'publish'
)));
foreach ($orders as $order) {
$woo = new WC_Order($order);
$stats->total += $woo->get_total();
$stats->count++;
}
return $stats;
}
return false;
}
/**
* @param WC_Order $order
* @return object
*/
public function getOrderAddresses(WC_Order $order)
{
// use the info from the order to compile an address.
$billing = new MailChimp_WooCommerce_Address();
$billing->setAddress1($order->billing_address_1);
$billing->setAddress2($order->billing_address_2);
$billing->setCity($order->billing_city);
$billing->setProvince($order->billing_state);
$billing->setPostalCode($order->billing_postcode);
$billing->setCountry($order->billing_country);
$billing->setPhone($order->billing_phone);
// if we have billing names go ahead and apply them
if (!empty($order->billing_first_name) && !empty($order->billing_last_name)) {
$billing->setName($order->billing_first_name.' '.$order->billing_last_name);
}
$shipping = new MailChimp_WooCommerce_Address();
$shipping->setAddress1($order->shipping_address_1);
$shipping->setAddress2($order->shipping_address_2);
$shipping->setCity($order->shipping_city);
$shipping->setProvince($order->shipping_state);
$shipping->setPostalCode($order->shipping_postcode);
$shipping->setCountry($order->shipping_country);
if (isset($order->shipping_phone)) {
$shipping->setPhone($order->shipping_phone);
}
// if we have shipping names go ahead and apply them
if (!empty($order->shipping_first_name) && !empty($order->shipping_last_name)) {
$shipping->setName($order->shipping_first_name.' '.$order->shipping_last_name);
}
return (object) array('billing' => $billing, 'shipping' => $shipping);
}
/**
* @param $user_id
* @param string $type
* @return MailChimp_WooCommerce_Address
*/
public function getUserAddress($user_id, $type = 'billing')
{
$address = new MailChimp_WooCommerce_Address();
// pull all the meta for this user.
$meta = get_user_meta($user_id);
// loop through all the possible address properties, and if we have on on the user, set the property
// because it's more up to date.
$address_props = array(
$type.'_address_1' => 'setAddress1',
$type.'_address_2' => 'setAddress2',
$type.'_city' => 'setCity',
$type.'_state' => 'setProvince',
$type.'_postcode' => 'setPostalCode',
$type.'_country' => 'setCountry',
$type.'_phone' => 'setPhone',
);
// loop through all the address properties and set the values if we have one.
foreach ($address_props as $address_key => $address_call) {
if (isset($meta[$address_key]) && !empty($meta[$address_key]) && isset($meta[$address_key][0])) {
$address->$address_call($meta[$address_key][0]);
}
}
return $address;
}
/**
* @return array
*/
public function getOrderStatuses()
{
return array(
// Order received (unpaid)
'pending' => (object) array(
'financial' => 'pending',
'fulfillment' => null
),
// Payment received and stock has been reduced the order is awaiting fulfillment.
// All product orders require processing, except those for digital downloads
'processing' => (object) array(
'financial' => 'pending',
'fulfillment' => null
),
// Awaiting payment stock is reduced, but you need to confirm payment
'on-hold' => (object) array(
'financial' => 'on-hold',
'fulfillment' => null
),
// Order fulfilled and complete requires no further action
'completed' => (object) array(
'financial' => 'fulfilled',
'fulfillment' => 'fulfilled'
),
// Cancelled by an admin or the customer no further action required
'cancelled' => (object) array(
'financial' => 'cancelled',
'fulfillment' => null
),
// Refunded by an admin no further action required
'refunded' => (object) array(
'financial' => 'refunded',
'fulfillment' => null
),
// Payment failed or was declined (unpaid). Note that this status may not show immediately and
// instead show as Pending until verified (i.e., PayPal)
'failed' => (object) array(
'financial' => 'failed',
'fulfillment' => null
),
);
}
}

View File

@@ -0,0 +1,283 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/13/16
* Time: 8:29 AM
*/
class MailChimp_WooCommerce_Transform_Products
{
/**
* @param int $page
* @param int $limit
* @return \stdClass
*/
public function compile($page = 1, $limit = 5)
{
$response = (object) array(
'endpoint' => 'products',
'page' => $page ? $page : 1,
'limit' => (int) $limit,
'count' => 0,
'stuffed' => false,
'items' => array(),
);
if ((($products = $this->getProductPosts($page, $limit)) && !empty($products))) {
foreach ($products as $post) {
$response->items[] = $this->transform($post);
$response->count++;
}
}
$response->stuffed = ($response->count > 0 && (int) $response->count === (int) $limit) ? true : false;
return $response;
}
/**
* @param WP_Post $post
* @return MailChimp_WooCommerce_Product
*/
public function transform(WP_Post $post)
{
if (!($woo = wc_get_product($post))) {
return $this->wooProductNotLoadedCorrectly($post);
}
$variant_posts = $this->getProductVariantPosts($post->ID);
$variants = $variant_posts ? array_merge(array($woo), $variant_posts) : array($woo);
$is_variant = count($variants) > 1;
$product = new MailChimp_WooCommerce_Product();
$product->setId($woo->get_id());
$product->setHandle($post->post_name);
$product->setImageUrl($this->getProductImage($post));
$product->setDescription($post->post_content);
$product->setPublishedAtForeign(mailchimp_date_utc($post->post_date));
$product->setTitle($woo->get_title());
$product->setUrl($woo->get_permalink());
foreach ($variants as $variant) {
$product_variant = $this->variant($is_variant, $variant, $woo->get_title());
$product_variant_title = $product_variant->getTitle();
if (empty($product_variant_title)) {
$product_variant->setTitle($woo->get_title());
}
$product_variant_image = $product_variant->getImageUrl();
if (empty($product_variant_image)) {
$product_variant->setImageUrl($product->getImageUrl());
}
$product->addVariant($product_variant);
}
return $product;
}
/**
* @param $is_variant
* @param WP_Post $post
* @param string $fallback_title
* @return MailChimp_WooCommerce_ProductVariation
*/
public function variant($is_variant, $post, $fallback_title = null)
{
if ($post instanceof WC_Product || $post instanceof WC_Product_Variation) {
$woo = $post;
} else {
if (isset($post->post_type) && $post->post_type === 'product_variation') {
$woo = new WC_Product_Variation($post->ID);
} else {
$woo = wc_get_product($post);
}
}
$variant = new MailChimp_WooCommerce_ProductVariation();
$variant->setId($woo->get_id());
$variant->setUrl($woo->get_permalink());
$variant->setImageUrl($this->getProductImage($post));
$variant->setPrice($woo->get_price());
$variant->setSku($woo->get_sku());
$variant->setBackorders($woo->backorders_allowed());
// only set these properties if the product is currently visible or purchasable.
if ($woo->is_purchasable() && $woo->is_visible()) {
if ($woo->is_in_stock()) {
$variant->setInventoryQuantity(($woo->managing_stock() ? $woo->get_stock_quantity() : 1000000));
} else {
$variant->setInventoryQuantity(0);
}
} else {
$variant->setInventoryQuantity(0);
}
if ($woo instanceof WC_Product_Variation) {
$variation_title = $woo->get_title();
if (empty($variation_title)) $variation_title = $fallback_title;
$title = array($variation_title);
foreach ($woo->get_variation_attributes() as $attribute => $value) {
if (is_string($value)) {
$name = ucfirst(str_replace(array('attribute_pa_', 'attribute_'), '', $attribute));
$title[] = "$name = $value";
}
}
$variant->setTitle(implode(' :: ', $title));
$variant->setVisibility(($woo->variation_is_visible() ? 'visible' : ''));
} else {
$variant->setVisibility(($woo->is_visible() ? 'visible' : ''));
$variant->setTitle($woo->get_title());
}
return $variant;
}
/**
* @param int $page
* @param int $posts
* @return array|bool
*/
public function getProductPosts($page = 1, $posts = 5)
{
$products = get_posts(array(
'post_type' => array_merge(array_keys(wc_get_product_types()), array('product')),
'posts_per_page' => $posts,
'paged' => $page,
'orderby' => 'ID',
'order' => 'ASC',
));
if (empty($products)) {
sleep(2);
$products = get_posts(array(
'post_type' => array_merge(array_keys(wc_get_product_types()), array('product')),
'posts_per_page' => $posts,
'paged' => $page,
'orderby' => 'ID',
'order' => 'ASC',
));
if (empty($products)) {
return false;
}
}
return $products;
}
/**
* @param $id
* @return array|bool
*/
public function getProductVariantPosts($id)
{
$variants = get_posts(array(
'numberposts' => 99999,
'order' => 'ASC',
'orderby' => 'ID',
'post_type' => 'product_variation',
'post_parent' => $id,
));
if (empty($variants)) {
return false;
}
return $variants;
}
/**
* @param $post_id
* @return false|string
*/
public function getProductImage($post_id)
{
$meta = get_post_meta($post_id);
$key = '_thumbnail_id';
$image_key = $this->getProductImageKey();
if ($meta && is_array($meta) && array_key_exists($key, $meta) && isset($meta[$key][0])) {
$img = wp_get_attachment_image($meta[$key][0], $image_key);
if (!empty($img)) return $img;
}
return get_the_post_thumbnail_url($post_id, $image_key);
}
/**
* @return null|string
*/
public function getProductImageKey()
{
return mailchimp_get_option('mailchimp_product_image_key', 'medium');
}
/**
* @param $id
* @return bool|MailChimp_WooCommerce_Product
* @throws Exception
*/
public static function deleted($id)
{
$store_id = mailchimp_get_store_id();
$api = mailchimp_get_api();
if (!($product = $api->getStoreProduct($store_id, "deleted_{$id}"))) {
$product = new MailChimp_WooCommerce_Product();
$product->setId("deleted_{$id}");
$product->setTitle("deleted_{$id}");
$variant = new MailChimp_WooCommerce_ProductVariation();
$variant->setId("deleted_{$id}");
$variant->setTitle("deleted_{$id}");
$product->addVariant($variant);
return $api->addStoreProduct($store_id, $product);
}
return $product;
}
/**
* @param \WP_Post $post
* @return MailChimp_WooCommerce_Product
*/
protected function wooProductNotLoadedCorrectly($post)
{
$product = new MailChimp_WooCommerce_Product();
$product->setId($post->ID);
$product->setHandle($post->post_name);
$product->setDescription($post->post_content);
$product->setImageUrl($this->getProductImage($post));
$variant = $this->variant(false, $post, $post->post_name);
if (!$variant->getImageUrl()) {
$variant->setImageUrl($product->getImageUrl());
}
$product->addVariant($variant);
return $product;
}
}

View File

@@ -0,0 +1,14 @@
<?php
/**
* Created by PhpStorm.
*
* User: kingpin
* Email: ryan@vextras.com
* Date: 6/18/15
* Time: 11:13 AM
*/
class MailChimp_WooCommerce_Error extends \Exception
{
}

View File

@@ -0,0 +1,14 @@
<?php
/**
* Created by PhpStorm.
*
* User: kingpin
* Email: ryan@vextras.com
* Date: 6/18/15
* Time: 11:13 AM
*/
class MailChimp_WooCommerce_ServerError extends MailChimp_WooCommerce_Error
{
}

View File

@@ -0,0 +1,135 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/12/16
* Time: 1:38 PM
*/
class MailChimp_WooCommerce_CurrencyCodes
{
/**
* @return array
*/
public static function all()
{
return array(
'AFA' => array('Afghan Afghani', '971'),
'AWG' => array('Aruban Florin', '533'),
'AUD' => array('Australian Dollars', '036'),
'ARS' => array('Argentine Pes', '032'),
'AZN' => array('Azerbaijanian Manat', '944'),
'BSD' => array('Bahamian Dollar', '044'),
'BDT' => array('Bangladeshi Taka', '050'),
'BBD' => array('Barbados Dollar', '052'),
'BYN' => array('Belarussian Rouble', '974'),
'BOB' => array('Bolivian Boliviano', '068'),
'BRL' => array('Brazilian Real', '986'),
'GBP' => array('British Pounds Sterling', '826'),
'BGN' => array('Bulgarian Lev', '975'),
'KHR' => array('Cambodia Riel', '116'),
'CAD' => array('Canadian Dollars', '124'),
'KYD' => array('Cayman Islands Dollar', '136'),
'CLP' => array('Chilean Peso', '152'),
'CNY' => array('Chinese Renminbi Yuan', '156'),
'COP' => array('Colombian Peso', '170'),
'CRC' => array('Costa Rican Colon', '188'),
'HRK' => array('Croatia Kuna', '191'),
'CPY' => array('Cypriot Pounds', '196'),
'CZK' => array('Czech Koruna', '203'),
'DKK' => array('Danish Krone', '208'),
'DOP' => array('Dominican Republic Peso', '214'),
'XCD' => array('East Caribbean Dollar', '951'),
'EGP' => array('Egyptian Pound', '818'),
'ERN' => array('Eritrean Nakfa', '232'),
'EEK' => array('Estonia Kroon', '233'),
'EUR' => array('Euro', '978'),
'GEL' => array('Georgian Lari', '981'),
'GHC' => array('Ghana Cedi', '288'),
'GIP' => array('Gibraltar Pound', '292'),
'GTQ' => array('Guatemala Quetzal', '320'),
'HNL' => array('Honduras Lempira', '340'),
'HKD' => array('Hong Kong Dollars', '344'),
'HUF' => array('Hungary Forint', '348'),
'ISK' => array('Icelandic Krona', '352'),
'INR' => array('Indian Rupee', '356'),
'IDR' => array('Indonesia Rupiah', '360'),
'ILS' => array('Israel Shekel', '376'),
'JMD' => array('Jamaican Dollar', '388'),
'JPY' => array('Japanese yen', '392'),
'KZT' => array('Kazakhstan Tenge', '368'),
'KES' => array('Kenyan Shilling', '404'),
'KWD' => array('Kuwaiti Dinar', '414'),
'LVL' => array('Latvia Lat', '428'),
'LBP' => array('Lebanese Pound', '422'),
'LTL' => array('Lithuania Litas', '440'),
'MDL' => array('Moldovan Leu', '498'),
'MOP' => array('Macau Pataca', '446'),
'MKD' => array('Macedonian Denar', '807'),
'MGA' => array('Malagascy Ariary', '969'),
'MYR' => array('Malaysian Ringgit', '458'),
'MTL' => array('Maltese Lira', '470'),
'BAM' => array('Marka', '977'),
'MUR' => array('Mauritius Rupee', '480'),
'MXN' => array('Mexican Pesos', '484'),
'MZM' => array('Mozambique Metical', '508'),
'NPR' => array('Nepalese Rupee', '524'),
'ANG' => array('Netherlands Antilles Guilder', '532'),
'TWD' => array('New Taiwanese Dollars', '901'),
'NZD' => array('New Zealand Dollars', '554'),
'NIO' => array('Nicaragua Cordoba', '558'),
'NGN' => array('Nigeria Naira', '566'),
'KPW' => array('North Korean Won', '408'),
'NOK' => array('Norwegian Krone', '578'),
'OMR' => array('Omani Riyal', '512'),
'PKR' => array('Pakistani Rupee', '586'),
'PYG' => array('Paraguay Guarani', '600'),
'PEN' => array('Peru New Sol', '604'),
'PHP' => array('Philippine Pesos', '608'),
'PLN' => array('Polish Zloty', '985'),
'QAR' => array('Qatari Riyal', '634'),
'RON' => array('Romanian New Leu', '946'),
'RUB' => array('Russian Federation Ruble', '643'),
'SAR' => array('Saudi Riyal', '682'),
'CSD' => array('Serbian Dinar', '891'),
'SCR' => array('Seychelles Rupee', '690'),
'SGD' => array('Singapore Dollars', '702'),
'SKK' => array('Slovak Koruna', '703'),
'SIT' => array('Slovenia Tolar', '705'),
'ZAR' => array('South African Rand', '710'),
'KRW' => array('South Korean Won', '410'),
'LKR' => array('Sri Lankan Rupee', '144'),
'SRD' => array('Surinam Dollar', '968'),
'SEK' => array('Swedish Krona', '752'),
'CHF' => array('Swiss Francs', '756'),
'TZS' => array('Tanzanian Shilling', '834'),
'THB' => array('Thai Baht', '764'),
'TTD' => array('Trinidad and Tobago Dollar', '780'),
'TRY' => array('Turkish New Lira', '949'),
'AED' => array('UAE Dirham', '784'),
'USD' => array('US Dollars', '840'),
'UGX' => array('Ugandian Shilling', '800'),
'UAH' => array('Ukraine Hryvna', '980'),
'UYU' => array('Uruguayan Peso', '858'),
'UZS' => array('Uzbekistani Som', '860'),
'VEB' => array('Venezuela Bolivar', '862'),
'VND' => array('Vietnam Dong', '704'),
'AMK' => array('Zambian Kwacha', '894'),
'ZWD' => array('Zimbabwe Dollar', '716'),
);
}
/**
* @return array
*/
public static function lists()
{
$response = array();
foreach (static::all() as $key => $data) {
$response[$key] = $data[0];
}
return $response;
}
}

View File

@@ -0,0 +1,469 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/12/16
* Time: 2:07 PM
*/
class MailChimp_Api_Locales
{
/**
* @return array
*/
public static function all()
{
return array(
"af_NA"=> "Afrikaans (Namibia)",
"af_ZA"=> "Afrikaans (South Africa)",
"af"=> "Afrikaans",
"ak_GH"=> "Akan (Ghana)",
"ak"=> "Akan",
"sq_AL"=> "Albanian (Albania)",
"sq"=> "Albanian",
"am_ET"=> "Amharic (Ethiopia)",
"am"=> "Amharic",
"ar_DZ"=> "Arabic (Algeria)",
"ar_BH"=> "Arabic (Bahrain)",
"ar_EG"=> "Arabic (Egypt)",
"ar_IQ"=> "Arabic (Iraq)",
"ar_JO"=> "Arabic (Jordan)",
"ar_KW"=> "Arabic (Kuwait)",
"ar_LB"=> "Arabic (Lebanon)",
"ar_LY"=> "Arabic (Libya)",
"ar_MA"=> "Arabic (Morocco)",
"ar_OM"=> "Arabic (Oman)",
"ar_QA"=> "Arabic (Qatar)",
"ar_SA"=> "Arabic (Saudi Arabia)",
"ar_SD"=> "Arabic (Sudan)",
"ar_SY"=> "Arabic (Syria)",
"ar_TN"=> "Arabic (Tunisia)",
"ar_AE"=> "Arabic (United Arab Emirates)",
"ar_YE"=> "Arabic (Yemen)",
"ar"=> "Arabic",
"hy_AM"=> "Armenian (Armenia)",
"hy"=> "Armenian",
"as_IN"=> "Assamese (India)",
"as"=> "Assamese",
"asa_TZ"=> "Asu (Tanzania)",
"asa"=> "Asu",
"az_Cyrl"=> "Azerbaijani (Cyrillic)",
"az_Cyrl_AZ"=> "Azerbaijani (Cyrillic, Azerbaijan)",
"az_Latn"=> "Azerbaijani (Latin)",
"az_Latn_AZ"=> "Azerbaijani (Latin, Azerbaijan)",
"az"=> "Azerbaijani",
"bm_ML"=> "Bambara (Mali)",
"bm"=> "Bambara",
"eu_ES"=> "Basque (Spain)",
"eu"=> "Basque",
"be_BY"=> "Belarusian (Belarus)",
"be"=> "Belarusian",
"bem_ZM"=> "Bemba (Zambia)",
"bem"=> "Bemba",
"bez_TZ"=> "Bena (Tanzania)",
"bez"=> "Bena",
"bn_BD"=> "Bengali (Bangladesh)",
"bn_IN"=> "Bengali (India)",
"bn"=> "Bengali",
"bs_BA"=> "Bosnian (Bosnia and Herzegovina)",
"bs"=> "Bosnian",
"bg_BG"=> "Bulgarian (Bulgaria)",
"bg"=> "Bulgarian",
"my_MM"=> "Burmese (Myanmar [Burma])",
"my"=> "Burmese",
"ca_ES"=> "Catalan (Spain)",
"ca"=> "Catalan",
"tzm_Latn"=> "Central Morocco Tamazight (Latin)",
"tzm_Latn_MA"=> "Central Morocco Tamazight (Latin, Morocco)",
"tzm"=> "Central Morocco Tamazight",
"chr_US"=> "Cherokee (United States)",
"chr"=> "Cherokee",
"cgg_UG"=> "Chiga (Uganda)",
"cgg"=> "Chiga",
"zh_Hans"=> "Chinese (Simplified Han)",
"zh_Hans_CN"=> "Chinese (Simplified Han, China)",
"zh_Hans_HK"=> "Chinese (Simplified Han, Hong Kong SAR China)",
"zh_Hans_MO"=> "Chinese (Simplified Han, Macau SAR China)",
"zh_Hans_SG"=> "Chinese (Simplified Han, Singapore)",
"zh_Hant"=> "Chinese (Traditional Han)",
"zh_Hant_HK"=> "Chinese (Traditional Han, Hong Kong SAR China)",
"zh_Hant_MO"=> "Chinese (Traditional Han, Macau SAR China)",
"zh_Hant_TW"=> "Chinese (Traditional Han, Taiwan)",
"zh"=> "Chinese",
"kw_GB"=> "Cornish (United Kingdom)",
"kw"=> "Cornish",
"hr_HR"=> "Croatian (Croatia)",
"hr"=> "Croatian",
"cs_CZ"=> "Czech (Czech Republic)",
"cs"=> "Czech",
"da_DK"=> "Danish (Denmark)",
"da"=> "Danish",
"nl_BE"=> "Dutch (Belgium)",
"nl_NL"=> "Dutch (Netherlands)",
"nl"=> "Dutch",
"ebu_KE"=> "Embu (Kenya)",
"ebu"=> "Embu",
"en_AS"=> "English (American Samoa)",
"en_AU"=> "English (Australia)",
"en_BE"=> "English (Belgium)",
"en_BZ"=> "English (Belize)",
"en_BW"=> "English (Botswana)",
"en_CA"=> "English (Canada)",
"en_GU"=> "English (Guam)",
"en_HK"=> "English (Hong Kong SAR China)",
"en_IN"=> "English (India)",
"en_IE"=> "English (Ireland)",
"en_JM"=> "English (Jamaica)",
"en_MT"=> "English (Malta)",
"en_MH"=> "English (Marshall Islands)",
"en_MU"=> "English (Mauritius)",
"en_NA"=> "English (Namibia)",
"en_NZ"=> "English (New Zealand)",
"en_MP"=> "English (Northern Mariana Islands)",
"en_PK"=> "English (Pakistan)",
"en_PH"=> "English (Philippines)",
"en_SG"=> "English (Singapore)",
"en_ZA"=> "English (South Africa)",
"en_TT"=> "English (Trinidad and Tobago)",
"en_UM"=> "English (U.S. Minor Outlying Islands)",
"en_VI"=> "English (U.S. Virgin Islands)",
"en_GB"=> "English (United Kingdom)",
"en_US"=> "English (United States)",
"en_ZW"=> "English (Zimbabwe)",
"en"=> "English",
"eo"=> "Esperanto",
"et_EE"=> "Estonian (Estonia)",
"et"=> "Estonian",
"ee_GH"=> "Ewe (Ghana)",
"ee_TG"=> "Ewe (Togo)",
"ee"=> "Ewe",
"fo_FO"=> "Faroese (Faroe Islands)",
"fo"=> "Faroese",
"fil_PH"=> "Filipino (Philippines)",
"fil"=> "Filipino",
"fi_FI"=> "Finnish (Finland)",
"fi"=> "Finnish",
"fr_BE"=> "French (Belgium)",
"fr_BJ"=> "French (Benin)",
"fr_BF"=> "French (Burkina Faso)",
"fr_BI"=> "French (Burundi)",
"fr_CM"=> "French (Cameroon)",
"fr_CA"=> "French (Canada)",
"fr_CF"=> "French (Central African Republic)",
"fr_TD"=> "French (Chad)",
"fr_KM"=> "French (Comoros)",
"fr_CG"=> "French (Congo - Brazzaville)",
"fr_CD"=> "French (Congo - Kinshasa)",
"fr_CI"=> "French (Côte dIvoire)",
"fr_DJ"=> "French (Djibouti)",
"fr_GQ"=> "French (Equatorial Guinea)",
"fr_FR"=> "French (France)",
"fr_GA"=> "French (Gabon)",
"fr_GP"=> "French (Guadeloupe)",
"fr_GN"=> "French (Guinea)",
"fr_LU"=> "French (Luxembourg)",
"fr_MG"=> "French (Madagascar)",
"fr_ML"=> "French (Mali)",
"fr_MQ"=> "French (Martinique)",
"fr_MC"=> "French (Monaco)",
"fr_NE"=> "French (Niger)",
"fr_RW"=> "French (Rwanda)",
"fr_RE"=> "French (Réunion)",
"fr_BL"=> "French (Saint Barthélemy)",
"fr_MF"=> "French (Saint Martin)",
"fr_SN"=> "French (Senegal)",
"fr_CH"=> "French (Switzerland)",
"fr_TG"=> "French (Togo)",
"fr"=> "French",
"ff_SN"=> "Fulah (Senegal)",
"ff"=> "Fulah",
"gl_ES"=> "Galician (Spain)",
"gl"=> "Galician",
"lg_UG"=> "Ganda (Uganda)",
"lg"=> "Ganda",
"ka_GE"=> "Georgian (Georgia)",
"ka"=> "Georgian",
"de_AT"=> "German (Austria)",
"de_BE"=> "German (Belgium)",
"de_DE"=> "German (Germany)",
"de_LI"=> "German (Liechtenstein)",
"de_LU"=> "German (Luxembourg)",
"de_CH"=> "German (Switzerland)",
"de"=> "German",
"el_CY"=> "Greek (Cyprus)",
"el_GR"=> "Greek (Greece)",
"el"=> "Greek",
"gu_IN"=> "Gujarati (India)",
"gu"=> "Gujarati",
"guz_KE"=> "Gusii (Kenya)",
"guz"=> "Gusii",
"ha_Latn"=> "Hausa (Latin)",
"ha_Latn_GH"=> "Hausa (Latin, Ghana)",
"ha_Latn_NE"=> "Hausa (Latin, Niger)",
"ha_Latn_NG"=> "Hausa (Latin, Nigeria)",
"ha"=> "Hausa",
"haw_US"=> "Hawaiian (United States)",
"haw"=> "Hawaiian",
"he_IL"=> "Hebrew (Israel)",
"he"=> "Hebrew",
"hi_IN"=> "Hindi (India)",
"hi"=> "Hindi",
"hu_HU"=> "Hungarian (Hungary)",
"hu"=> "Hungarian",
"is_IS"=> "Icelandic (Iceland)",
"is"=> "Icelandic",
"ig_NG"=> "Igbo (Nigeria)",
"ig"=> "Igbo",
"id_ID"=> "Indonesian (Indonesia)",
"id"=> "Indonesian",
"ga_IE"=> "Irish (Ireland)",
"ga"=> "Irish",
"it_IT"=> "Italian (Italy)",
"it_CH"=> "Italian (Switzerland)",
"it"=> "Italian",
"ja_JP"=> "Japanese (Japan)",
"ja"=> "Japanese",
"kea_CV"=> "Kabuverdianu (Cape Verde)",
"kea"=> "Kabuverdianu",
"kab_DZ"=> "Kabyle (Algeria)",
"kab"=> "Kabyle",
"kl_GL"=> "Kalaallisut (Greenland)",
"kl"=> "Kalaallisut",
"kln_KE"=> "Kalenjin (Kenya)",
"kln"=> "Kalenjin",
"kam_KE"=> "Kamba (Kenya)",
"kam"=> "Kamba",
"kn_IN"=> "Kannada (India)",
"kn"=> "Kannada",
"kk_Cyrl"=> "Kazakh (Cyrillic)",
"kk_Cyrl_KZ"=> "Kazakh (Cyrillic, Kazakhstan)",
"kk"=> "Kazakh",
"km_KH"=> "Khmer (Cambodia)",
"km"=> "Khmer",
"ki_KE"=> "Kikuyu (Kenya)",
"ki"=> "Kikuyu",
"rw_RW"=> "Kinyarwanda (Rwanda)",
"rw"=> "Kinyarwanda",
"kok_IN"=> "Konkani (India)",
"kok"=> "Konkani",
"ko_KR"=> "Korean (South Korea)",
"ko"=> "Korean",
"khq_ML"=> "Koyra Chiini (Mali)",
"khq"=> "Koyra Chiini",
"ses_ML"=> "Koyraboro Senni (Mali)",
"ses"=> "Koyraboro Senni",
"lag_TZ"=> "Langi (Tanzania)",
"lag"=> "Langi",
"lv_LV"=> "Latvian (Latvia)",
"lv"=> "Latvian",
"lt_LT"=> "Lithuanian (Lithuania)",
"lt"=> "Lithuanian",
"luo_KE"=> "Luo (Kenya)",
"luo"=> "Luo",
"luy_KE"=> "Luyia (Kenya)",
"luy"=> "Luyia",
"mk_MK"=> "Macedonian (Macedonia)",
"mk"=> "Macedonian",
"jmc_TZ"=> "Machame (Tanzania)",
"jmc"=> "Machame",
"kde_TZ"=> "Makonde (Tanzania)",
"kde"=> "Makonde",
"mg_MG"=> "Malagasy (Madagascar)",
"mg"=> "Malagasy",
"ms_BN"=> "Malay (Brunei)",
"ms_MY"=> "Malay (Malaysia)",
"ms"=> "Malay",
"ml_IN"=> "Malayalam (India)",
"ml"=> "Malayalam",
"mt_MT"=> "Maltese (Malta)",
"mt"=> "Maltese",
"gv_GB"=> "Manx (United Kingdom)",
"gv"=> "Manx",
"mr_IN"=> "Marathi (India)",
"mr"=> "Marathi",
"mas_KE"=> "Masai (Kenya)",
"mas_TZ"=> "Masai (Tanzania)",
"mas"=> "Masai",
"mer_KE"=> "Meru (Kenya)",
"mer"=> "Meru",
"mfe_MU"=> "Morisyen (Mauritius)",
"mfe"=> "Morisyen",
"naq_NA"=> "Nama (Namibia)",
"naq"=> "Nama",
"ne_IN"=> "Nepali (India)",
"ne_NP"=> "Nepali (Nepal)",
"ne"=> "Nepali",
"nd_ZW"=> "North Ndebele (Zimbabwe)",
"nd"=> "North Ndebele",
"nb_NO"=> "Norwegian Bokmål (Norway)",
"nb"=> "Norwegian Bokmål",
"nn_NO"=> "Norwegian Nynorsk (Norway)",
"nn"=> "Norwegian Nynorsk",
"nyn_UG"=> "Nyankole (Uganda)",
"nyn"=> "Nyankole",
"or_IN"=> "Oriya (India)",
"or"=> "Oriya",
"om_ET"=> "Oromo (Ethiopia)",
"om_KE"=> "Oromo (Kenya)",
"om"=> "Oromo",
"ps_AF"=> "Pashto (Afghanistan)",
"ps"=> "Pashto",
"fa_AF"=> "Persian (Afghanistan)",
"fa_IR"=> "Persian (Iran)",
"fa"=> "Persian",
"pl_PL"=> "Polish (Poland)",
"pl"=> "Polish",
"pt_BR"=> "Portuguese (Brazil)",
"pt_GW"=> "Portuguese (Guinea-Bissau)",
"pt_MZ"=> "Portuguese (Mozambique)",
"pt_PT"=> "Portuguese (Portugal)",
"pt"=> "Portuguese",
"pa_Arab"=> "Punjabi (Arabic)",
"pa_Arab_PK"=> "Punjabi (Arabic, Pakistan)",
"pa_Guru"=> "Punjabi (Gurmukhi)",
"pa_Guru_IN"=> "Punjabi (Gurmukhi, India)",
"pa"=> "Punjabi",
"ro_MD"=> "Romanian (Moldova)",
"ro_RO"=> "Romanian (Romania)",
"ro"=> "Romanian",
"rm_CH"=> "Romansh (Switzerland)",
"rm"=> "Romansh",
"rof_TZ"=> "Rombo (Tanzania)",
"rof"=> "Rombo",
"ru_MD"=> "Russian (Moldova)",
"ru_RU"=> "Russian (Russia)",
"ru_UA"=> "Russian (Ukraine)",
"ru"=> "Russian",
"rwk_TZ"=> "Rwa (Tanzania)",
"rwk"=> "Rwa",
"saq_KE"=> "Samburu (Kenya)",
"saq"=> "Samburu",
"sg_CF"=> "Sango (Central African Republic)",
"sg"=> "Sango",
"seh_MZ"=> "Sena (Mozambique)",
"seh"=> "Sena",
"sr_Cyrl"=> "Serbian (Cyrillic)",
"sr_Cyrl_BA"=> "Serbian (Cyrillic, Bosnia and Herzegovina)",
"sr_Cyrl_ME"=> "Serbian (Cyrillic, Montenegro)",
"sr_Cyrl_RS"=> "Serbian (Cyrillic, Serbia)",
"sr_Latn"=> "Serbian (Latin)",
"sr_Latn_BA"=> "Serbian (Latin, Bosnia and Herzegovina)",
"sr_Latn_ME"=> "Serbian (Latin, Montenegro)",
"sr_Latn_RS"=> "Serbian (Latin, Serbia)",
"sr"=> "Serbian",
"sn_ZW"=> "Shona (Zimbabwe)",
"sn"=> "Shona",
"ii_CN"=> "Sichuan Yi (China)",
"ii"=> "Sichuan Yi",
"si_LK"=> "Sinhala (Sri Lanka)",
"si"=> "Sinhala",
"sk_SK"=> "Slovak (Slovakia)",
"sk"=> "Slovak",
"sl_SI"=> "Slovenian (Slovenia)",
"sl"=> "Slovenian",
"xog_UG"=> "Soga (Uganda)",
"xog"=> "Soga",
"so_DJ"=> "Somali (Djibouti)",
"so_ET"=> "Somali (Ethiopia)",
"so_KE"=> "Somali (Kenya)",
"so_SO"=> "Somali (Somalia)",
"so"=> "Somali",
"es_AR"=> "Spanish (Argentina)",
"es_BO"=> "Spanish (Bolivia)",
"es_CL"=> "Spanish (Chile)",
"es_CO"=> "Spanish (Colombia)",
"es_CR"=> "Spanish (Costa Rica)",
"es_DO"=> "Spanish (Dominican Republic)",
"es_EC"=> "Spanish (Ecuador)",
"es_SV"=> "Spanish (El Salvador)",
"es_GQ"=> "Spanish (Equatorial Guinea)",
"es_GT"=> "Spanish (Guatemala)",
"es_HN"=> "Spanish (Honduras)",
"es_419"=> "Spanish (Latin America)",
"es_MX"=> "Spanish (Mexico)",
"es_NI"=> "Spanish (Nicaragua)",
"es_PA"=> "Spanish (Panama)",
"es_PY"=> "Spanish (Paraguay)",
"es_PE"=> "Spanish (Peru)",
"es_PR"=> "Spanish (Puerto Rico)",
"es_ES"=> "Spanish (Spain)",
"es_US"=> "Spanish (United States)",
"es_UY"=> "Spanish (Uruguay)",
"es_VE"=> "Spanish (Venezuela)",
"es"=> "Spanish",
"sw_KE"=> "Swahili (Kenya)",
"sw_TZ"=> "Swahili (Tanzania)",
"sw"=> "Swahili",
"sv_FI"=> "Swedish (Finland)",
"sv_SE"=> "Swedish (Sweden)",
"sv"=> "Swedish",
"gsw_CH"=> "Swiss German (Switzerland)",
"gsw"=> "Swiss German",
"shi_Latn"=> "Tachelhit (Latin)",
"shi_Latn_MA"=> "Tachelhit (Latin, Morocco)",
"shi_Tfng"=> "Tachelhit (Tifinagh)",
"shi_Tfng_MA"=> "Tachelhit (Tifinagh, Morocco)",
"shi"=> "Tachelhit",
"dav_KE"=> "Taita (Kenya)",
"dav"=> "Taita",
"ta_IN"=> "Tamil (India)",
"ta_LK"=> "Tamil (Sri Lanka)",
"ta"=> "Tamil",
"te_IN"=> "Telugu (India)",
"te"=> "Telugu",
"teo_KE"=> "Teso (Kenya)",
"teo_UG"=> "Teso (Uganda)",
"teo"=> "Teso",
"th_TH"=> "Thai (Thailand)",
"th"=> "Thai",
"bo_CN"=> "Tibetan (China)",
"bo_IN"=> "Tibetan (India)",
"bo"=> "Tibetan",
"ti_ER"=> "Tigrinya (Eritrea)",
"ti_ET"=> "Tigrinya (Ethiopia)",
"ti"=> "Tigrinya",
"to_TO"=> "Tonga (Tonga)",
"to"=> "Tonga",
"tr_TR"=> "Turkish (Turkey)",
"tr"=> "Turkish",
"uk_UA"=> "Ukrainian (Ukraine)",
"uk"=> "Ukrainian",
"ur_IN"=> "Urdu (India)",
"ur_PK"=> "Urdu (Pakistan)",
"ur"=> "Urdu",
"uz_Arab"=> "Uzbek (Arabic)",
"uz_Arab_AF"=> "Uzbek (Arabic, Afghanistan)",
"uz_Cyrl"=> "Uzbek (Cyrillic)",
"uz_Cyrl_UZ"=> "Uzbek (Cyrillic, Uzbekistan)",
"uz_Latn"=> "Uzbek (Latin)",
"uz_Latn_UZ"=> "Uzbek (Latin, Uzbekistan)",
"uz"=> "Uzbek",
"vi_VN"=> "Vietnamese (Vietnam)",
"vi"=> "Vietnamese",
"vun_TZ"=> "Vunjo (Tanzania)",
"vun"=> "Vunjo",
"cy_GB"=> "Welsh (United Kingdom)",
"cy"=> "Welsh",
"yo_NG"=> "Yoruba (Nigeria)",
"yo"=> "Yoruba",
"zu_ZA"=> "Zulu (South Africa)",
"zu"=> "Zulu"
);
}
/**
* @return array
*/
public static function simple()
{
$response = array();
foreach (static::all() as $key => $value) {
if (!strpos($key, '_') > 0) {
$response[$key] = $value;
}
}
return $response;
}
}

View File

@@ -0,0 +1,100 @@
<?php
/**
* Fired during plugin activation.
*
* This class defines all code necessary to run during the plugin's activation.
*
* @since 1.0.1
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
* @author Ryan Hungate <ryan@vextras.com>
*/
class MailChimp_WooCommerce_Activator {
/**
* Short Description. (use period)
*
* Long Description.
*
* @since 1.0.0
*/
public static function activate() {
// create the queue tables because we need them for the sync jobs.
static::create_queue_tables();
// update the settings so we have them for use.
$saved_options = get_option('mailchimp-woocommerce', false);
// if we haven't saved options previously, we will need to create the site id and update base options
if (empty($saved_options)) {
mailchimp_clean_database();
update_option('mailchimp-woocommerce', array());
// only do this if the option has never been set before.
if (!is_multisite()) {
add_option('mailchimp_woocommerce_plugin_do_activation_redirect', true);
}
}
// if we haven't saved the store id yet.
$saved_store_id = get_option('mailchimp-woocommerce-store_id', false);
if (empty($saved_store_id)) {
// add a store id flag which will be a random hash
update_option('mailchimp-woocommerce-store_id', uniqid(), 'yes');
}
if (class_exists('MailChimp_WooCommerce_MailChimpApi')) {
// try this now for existing stores on an update.
mailchimp_update_connected_site_script();
}
}
/**
* Create the queue tables in the DB so we can use it for syncing.
*/
public static function create_queue_tables()
{
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
global $wpdb;
$wpdb->hide_errors();
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}queue (
id bigint(20) NOT NULL AUTO_INCREMENT,
job text NOT NULL,
attempts tinyint(1) NOT NULL DEFAULT 0,
locked tinyint(1) NOT NULL DEFAULT 0,
locked_at datetime DEFAULT NULL,
available_at datetime NOT NULL,
created_at datetime NOT NULL,
PRIMARY KEY (id)
) $charset_collate;";
dbDelta( $sql );
$sql = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}failed_jobs (
id bigint(20) NOT NULL AUTO_INCREMENT,
job text NOT NULL,
failed_at datetime NOT NULL,
PRIMARY KEY (id)
) $charset_collate;";
dbDelta( $sql );
$sql = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}mailchimp_carts (
id VARCHAR (255) NOT NULL,
email VARCHAR (100) NOT NULL,
user_id INT (11) DEFAULT NULL,
cart text NOT NULL,
created_at datetime NOT NULL
) $charset_collate;";
dbDelta( $sql );
// set the mailchimp woocommerce version at the time of install
update_site_option('mailchimp_woocommerce_version', mailchimp_environment_variables()->version);
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* Fired during plugin deactivation
*
* @link https://mailchimp.com
* @since 1.0.1
*
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
*/
/**
* Fired during plugin deactivation.
*
* This class defines all code necessary to run during the plugin's deactivation.
*
* @since 1.0.1
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
* @author Ryan Hungate <ryan@vextras.com>
*/
class MailChimp_WooCommerce_Deactivator {
/**
* Short Description. (use period)
*
* Long Description.
*
* @since 1.0.0
*/
public static function deactivate() {
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* Define the internationalization functionality
*
* Loads and defines the internationalization files for this plugin
* so that it is ready for translation.
*
* @link https://mailchimp.com
* @since 1.0.1
*
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
*/
/**
* Define the internationalization functionality.
*
* Loads and defines the internationalization files for this plugin
* so that it is ready for translation.
*
* @since 1.0.1
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
* @author Ryan Hungate <ryan@vextras.com>
*/
class MailChimp_WooCommerce_i18n {
/**
* Load the plugin text domain for translation.
*
* @since 1.0.0
*/
public function load_plugin_textdomain() {
load_plugin_textdomain(
'mailchimp-woocommerce',
false,
dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/languages/'
);
}
}

View File

@@ -0,0 +1,129 @@
<?php
/**
* Register all actions and filters for the plugin
*
* @link https://mailchimp.com
* @since 1.0.1
*
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
*/
/**
* Register all actions and filters for the plugin.
*
* Maintain a list of all hooks that are registered throughout
* the plugin, and register them with the WordPress API. Call the
* run function to execute the list of actions and filters.
*
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
* @author Ryan Hungate <ryan@vextras.com>
*/
class MailChimp_WooCommerce_Loader {
/**
* The array of actions registered with WordPress.
*
* @since 1.0.0
* @access protected
* @var array $actions The actions registered with WordPress to fire when the plugin loads.
*/
protected $actions;
/**
* The array of filters registered with WordPress.
*
* @since 1.0.0
* @access protected
* @var array $filters The filters registered with WordPress to fire when the plugin loads.
*/
protected $filters;
/**
* Initialize the collections used to maintain the actions and filters.
*
* @since 1.0.0
*/
public function __construct() {
$this->actions = array();
$this->filters = array();
}
/**
* Add a new action to the collection to be registered with WordPress.
*
* @since 1.0.0
* @param string $hook The name of the WordPress action that is being registered.
* @param object $component A reference to the instance of the object on which the action is defined.
* @param string $callback The name of the function definition on the $component.
* @param int $priority Optional. he priority at which the function should be fired. Default is 10.
* @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1.
*/
public function add_action( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) {
$this->actions = $this->add( $this->actions, $hook, $component, $callback, $priority, $accepted_args );
}
/**
* Add a new filter to the collection to be registered with WordPress.
*
* @since 1.0.0
* @param string $hook The name of the WordPress filter that is being registered.
* @param object $component A reference to the instance of the object on which the filter is defined.
* @param string $callback The name of the function definition on the $component.
* @param int $priority Optional. he priority at which the function should be fired. Default is 10.
* @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1
*/
public function add_filter( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) {
$this->filters = $this->add( $this->filters, $hook, $component, $callback, $priority, $accepted_args );
}
/**
* A utility function that is used to register the actions and hooks into a single
* collection.
*
* @since 1.0.0
* @access private
* @param array $hooks The collection of hooks that is being registered (that is, actions or filters).
* @param string $hook The name of the WordPress filter that is being registered.
* @param object $component A reference to the instance of the object on which the filter is defined.
* @param string $callback The name of the function definition on the $component.
* @param int $priority The priority at which the function should be fired.
* @param int $accepted_args The number of arguments that should be passed to the $callback.
* @return array The collection of actions and filters registered with WordPress.
*/
private function add( $hooks, $hook, $component, $callback, $priority, $accepted_args ) {
$hooks[] = array(
'hook' => $hook,
'component' => $component,
'callback' => $callback,
'priority' => $priority,
'accepted_args' => $accepted_args
);
return $hooks;
}
/**
* Register the filters and actions with WordPress.
*
* @since 1.0.0
*/
public function run() {
foreach ( $this->filters as $hook ) {
add_filter( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
}
foreach ( $this->actions as $hook ) {
add_action( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
}
}
}

View File

@@ -0,0 +1,110 @@
<?php
/**
* Created by MailChimp.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 2/22/16
* Time: 9:09 AM
*/
class MailChimp_Newsletter extends MailChimp_WooCommerce_Options
{
/**
* @param WC_Checkout $checkout
*/
public function applyNewsletterField($checkout)
{
if (!is_admin()) {
// if the user has chosen to hide the checkbox, don't do anything.
if (($default_setting = $this->getOption('mailchimp_checkbox_defaults', 'check')) === 'hide') {
return;
}
// allow the user to specify the text in the newsletter label.
$label = $this->getOption('newsletter_label', 'Subscribe to our newsletter');
// if the user chose 'check' or nothing at all, we default to true.
$default_checked = $default_setting === 'check';
$status = $default_checked;
// if the user is logged in, we will pull the 'is_subscribed' property out of the meta for the value.
// otherwise we use the default settings.
if (is_user_logged_in()) {
$status = get_user_meta(get_current_user_id(), 'mailchimp_woocommerce_is_subscribed', true);
/// if the user is logged in - and is already subscribed - just ignore this checkbox.
if ((bool) $status) {
return;
}
if ($status === '' || $status === null) {
$status = $default_checked;
}
}
// echo out the checkbox.
$checkbox = '<p class="form-row form-row-wide create-account">';
$checkbox .= '<label for="mailchimp_woocommerce_newsletter" class="woocommerce-form__label woocommerce-form__label-for-checkbox checkbox">';
$checkbox .= '<input class="woocommerce-form__input woocommerce-form__input-checkbox input-checkbox" id="mailchimp_woocommerce_newsletter" type="checkbox" ';
$checkbox .= 'name="mailchimp_woocommerce_newsletter" value="1"'.($status ? ' checked="checked"' : '').'> ';
$checkbox .= '<span>' . $label . '</span>';
$checkbox .= '</label>';
$checkbox .= '</p>';
$checkbox .= '<div class="clear"></div>';
echo $checkbox;
}
}
/**
* @param $order_id
* @param $posted
*/
public function processNewsletterField($order_id, $posted)
{
$this->handleStatus($order_id);
}
/**
* @param WC_Order $order
*/
public function processPayPalNewsletterField($order)
{
$this->handleStatus($order->get_id());
}
/**
* @param $sanitized_user_login
* @param $user_email
* @param $reg_errors
*/
public function processRegistrationForm($sanitized_user_login, $user_email, $reg_errors)
{
if (defined('WOOCOMMERCE_CHECKOUT')) {
return; // Ship checkout
}
$this->handleStatus();
}
/**
* @param null $order_id
* @return bool|int
*/
protected function handleStatus($order_id = null)
{
$status = isset($_POST['mailchimp_woocommerce_newsletter']) ? (int)$_POST['mailchimp_woocommerce_newsletter'] : 0;
if ($order_id) {
update_post_meta($order_id, 'mailchimp_woocommerce_is_subscribed', $status);
}
if (is_user_logged_in()) {
update_user_meta(get_current_user_id(), 'mailchimp_woocommerce_is_subscribed', $status);
return $status;
}
return false;
}
}

View File

@@ -0,0 +1,311 @@
<?php
/**
* Created by MailChimp.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 2/22/16
* Time: 3:45 PM
*/
abstract class MailChimp_WooCommerce_Options
{
/**
* @var MailChimp_WooCommerce_MailChimpApi
*/
protected $api;
protected $plugin_name = 'mailchimp-woocommerce';
protected $environment = 'production';
protected $version = '1.0.0';
protected $plugin_options = null;
protected $is_admin = false;
/**
* hook calls this so that we know the admin is here.
*/
public function adminReady()
{
$this->is_admin = current_user_can('administrator');
if (get_option('mailchimp_woocommerce_plugin_do_activation_redirect', false)) {
delete_option('mailchimp_woocommerce_plugin_do_activation_redirect');
// don't do the redirect while activating the plugin through the rest API. ( Bartosz from Woo asked for this )
if ((defined( 'REST_REQUEST' ) && REST_REQUEST)) {
return;
}
if (!isset($_GET['activate-multi'])) {
wp_redirect("options-general.php?page=mailchimp-woocommerce");
}
}
}
/**
* @return bool
*/
public function isAdmin()
{
return $this->is_admin;
}
/**
* @param $version
*/
public function setVersion($version)
{
$this->version = $version;
}
/**
* @return string
*/
public function getVersion()
{
return $this->version;
}
/**
* @return string
*/
public function getUniqueStoreID()
{
return mailchimp_get_store_id();
}
/**
* @param $env
* @return $this
*/
public function setEnvironment($env)
{
$this->environment = $env;
return $this;
}
/**
* @return string
*/
public function getEnvironment()
{
return $this->environment;
}
/**
* @param $key
* @param null $default
* @return null
*/
public function getOption($key, $default = null)
{
$options = $this->getOptions();
if (isset($options[$key])) {
return $options[$key];
}
return $default;
}
/**
* @param $key
* @param bool $default
* @return bool
*/
public function hasOption($key, $default = false)
{
return (bool) $this->getOption($key, $default);
}
/**
* @return array
*/
public function resetOptions()
{
return $this->plugin_options = get_option($this->plugin_name);
}
/**
* @return array
*/
public function getOptions()
{
if (empty($this->plugin_options)) {
$this->plugin_options = get_option($this->plugin_name);
}
return is_array($this->plugin_options) ? $this->plugin_options : array();
}
/**
* @param $key
* @param $value
* @return $this
*/
public function setData($key, $value)
{
update_option($this->plugin_name.'-'.$key, $value, 'yes');
return $this;
}
/**
* @param $key
* @param null $default
* @return mixed|void
*/
public function getData($key, $default = null)
{
return get_option($this->plugin_name.'-'.$key, $default);
}
/**
* @param $key
* @return bool
*/
public function removeData($key)
{
return delete_option($this->plugin_name.'-'.$key);
}
/**
* @param $key
* @param null $default
* @return null|mixed
*/
public function getCached($key, $default = null)
{
$cached = $this->getData("cached-$key", false);
if (empty($cached) || !($cached = unserialize($cached))) {
return $default;
}
if (empty($cached['till']) || (time() > $cached['till'])) {
$this->removeData("cached-$key");
return $default;
}
return $cached['value'];
}
/**
* @param $key
* @param $value
* @param $seconds
* @return $this
*/
public function setCached($key, $value, $seconds = 60)
{
$time = time();
$data = array('at' => $time, 'till' => $time + $seconds, 'value' => $value);
$this->setData("cached-$key", serialize($data));
return $this;
}
/**
* @param $key
* @param $callable
* @param int $seconds
* @return mixed|null
*/
public function getCachedWithSetDefault($key, $callable, $seconds = 60)
{
if (!($value = $this->getCached($key, false))) {
$value = call_user_func($callable);
$this->setCached($key, $value, $seconds);
}
return $value;
}
/**
* @return bool
*/
public function isConfigured()
{
return true;
//return $this->getOption('public_key', false) && $this->getOption('secret_key', false);
}
/**
* @return bool
*/
protected function doingAjax()
{
return defined('DOING_AJAX') && DOING_AJAX;
}
/**
* @return MailChimp_WooCommerce_MailChimpApi
*/
public function api()
{
if (empty($this->api)) {
$this->api = new MailChimp_WooCommerce_MailChimpApi($this->getOption('mailchimp_api_key', false));
}
return $this->api;
}
/**
* @param array $data
* @param $key
* @param null $default
* @return null|mixed
*/
public function array_get(array $data, $key, $default = null)
{
if (isset($data[$key])) {
return $data[$key];
}
return $default;
}
/**
* @param bool $products
* @param bool $orders
* @return $this
*/
public function removePointers($products = true, $orders = true)
{
if ($products) {
$this->removeProductPointers();
}
if ($orders) {
$this->removeOrderPointers();
}
$this->removeSyncPointers();
$this->removeMiscPointers();
return $this;
}
public function removeProductPointers()
{
delete_option('mailchimp-woocommerce-sync.products.completed_at');
delete_option('mailchimp-woocommerce-sync.products.current_page');
}
public function removeOrderPointers()
{
delete_option('mailchimp-woocommerce-sync.orders.prevent');
delete_option('mailchimp-woocommerce-sync.orders.completed_at');
delete_option('mailchimp-woocommerce-sync.orders.current_page');
}
public function removeSyncPointers()
{
delete_option('mailchimp-woocommerce-sync.orders.prevent');
delete_option('mailchimp-woocommerce-sync.syncing');
delete_option('mailchimp-woocommerce-sync.started_at');
delete_option('mailchimp-woocommerce-sync.completed_at');
}
public function removeMiscPointers()
{
delete_option('mailchimp-woocommerce-errors.store_info');
delete_option('mailchimp-woocommerce-validation.api.ping');
delete_option('mailchimp-woocommerce-cached-api-lists');
delete_option('mailchimp-woocommerce-cached-api-ping-check');
}
}

View File

@@ -0,0 +1,730 @@
<?php
/**
* Created by MailChimp.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 2/17/16
* Time: 12:03 PM
*/
class MailChimp_Service extends MailChimp_WooCommerce_Options
{
protected static $pushed_orders = array();
protected $user_email = null;
protected $previous_email = null;
protected $force_cart_post = false;
protected $cart_was_submitted = false;
protected $cart = array();
protected $validated_cart_db = false;
/**
* hook fired when we know everything is booted
*/
public function wooIsRunning()
{
// make sure the site option for setting the mailchimp_carts has been saved.
$this->validated_cart_db = get_site_option('mailchimp_woocommerce_db_mailchimp_carts', false);
$this->is_admin = current_user_can('administrator');
}
/**
* @param $r
* @param $url
* @return mixed
*/
public function addHttpRequestArgs( $r, $url ) {
// not sure whether or not we need to implement something like this yet.
//$r['headers']['Authorization'] = 'Basic ' . base64_encode('username:password');
return $r;
}
/**
* @param $key
* @param $default
* @return mixed
*/
protected function cookie($key, $default = null)
{
if ($this->is_admin) {
return $default;
}
return isset($_COOKIE[$key]) ? $_COOKIE[$key] : $default;
}
/**
* @param WC_Order $order
*/
public function onNewPayPalOrder($order)
{
$this->onNewOrder($order->get_id());
}
/**
* This should only fire on a web based order so we can do real campaign tracking here.
*
* @param $order_id
*/
public function onNewOrder($order_id)
{
if (!mailchimp_is_configured()) return;
// register this order is already in process..
static::$pushed_orders[$order_id] = true;
// see if we have a session id and a campaign id, also only do this when this user is not the admin.
$campaign_id = $this->getCampaignTrackingID();
// grab the landing site cookie if we have one here.
$landing_site = $this->getLandingSiteCookie();
// expire the landing site cookie so we can rinse and repeat tracking
$this->expireLandingSiteCookie();
// remove this record from the db.
$this->clearCartData();
// queue up the single order to be processed.
$handler = new MailChimp_WooCommerce_Single_Order($order_id, null, $campaign_id, $landing_site);
wp_queue($handler, 60);
}
/**
* @param $order_id
* @param bool $is_admin
*/
public function handleOrderStatusChanged($order_id, $is_admin = false)
{
if (!mailchimp_is_configured()) return;
// register this order is already in process..
static::$pushed_orders[$order_id] = true;
// queue up the single order to be processed.
$handler = new MailChimp_WooCommerce_Single_Order($order_id, null, null, null);
$handler->is_update = true;
$handler->is_admin_save = $is_admin;
wp_queue($handler, 90);
}
/**
* @param $order_id
*/
public function onPartiallyRefunded($order_id)
{
if (!mailchimp_is_configured()) return;
$handler = new MailChimp_WooCommerce_Single_Order($order_id, null, null, null);
$handler->partially_refunded = true;
wp_queue($handler);
}
/**
* Clear the card data for a user.
*/
public function clearCartData()
{
if ($user_email = $this->getCurrentUserEmail()) {
$this->deleteCart($user_email);
}
}
/**
* @param null $updated
* @return bool|null
*/
public function handleCartUpdated($updated = null)
{
if ($updated === false || $this->is_admin || $this->cart_was_submitted || !mailchimp_is_configured()) {
return !is_null($updated) ? $updated : false;
}
if (empty($this->cart)) {
$this->cart = $this->getCartItems();
}
if (($user_email = $this->getCurrentUserEmail())) {
$previous = $this->getPreviousEmailFromSession();
$uid = md5(trim(strtolower($user_email)));
// delete the previous records.
if (!empty($previous) && $previous !== $user_email) {
if ($this->api()->deleteCartByID($this->getUniqueStoreID(), $previous_email = md5(trim(strtolower($previous))))) {
mailchimp_log('ac.cart_swap', "Deleted cart [$previous] :: ID [$previous_email]");
}
// going to delete the cart because we are switching.
$this->deleteCart($previous_email);
}
if ($this->cart && !empty($this->cart)) {
// track the cart locally so we can repopulate things for cross device compatibility.
$this->trackCart($uid, $user_email);
$this->cart_was_submitted = true;
// grab the cookie data that could play important roles in the submission
$campaign = $this->getCampaignTrackingID();
// fire up the job handler
$handler = new MailChimp_WooCommerce_Cart_Update($uid, $user_email, $campaign, $this->cart);
wp_queue($handler);
}
return !is_null($updated) ? $updated : true;
}
return !is_null($updated) ? $updated : false;
}
/**
* @param $post_id
*/
public function handleNewCoupon($post_id)
{
$this->handleCouponSaved($post_id, new WC_Coupon($post_id));
}
/**
* @param $post_id
* @param null $coupon
*/
public function handleCouponSaved($post_id, $coupon = null)
{
if (!mailchimp_is_configured()) return;
if ($coupon instanceof WC_Coupon) {
wp_queue(new MailChimp_WooCommerce_SingleCoupon($post_id));
}
}
/**
* @param $post_id
*/
public function handleCouponRestored($post_id)
{
$this->handleCouponSaved($post_id, new WC_Coupon($post_id));
}
/**
* Save post metadata when a post is saved.
*
* @param int $post_id The post ID.
* @param WP_Post $post The post object.
* @param bool $update Whether this is an existing post being updated or not.
*/
public function handlePostSaved($post_id, $post, $update)
{
if (!mailchimp_is_configured()) return;
if ($post->post_status !== 'auto-draft') {
if ('product' == $post->post_type) {
wp_queue(new MailChimp_WooCommerce_Single_Product($post_id), 5);
} elseif ('shop_order' == $post->post_type) {
$this->handleOrderStatusChanged($post_id, is_admin());
}
}
}
/**
* @param $post_id
*/
public function handlePostTrashed($post_id)
{
if (!mailchimp_is_configured()) return;
switch (get_post_type($post_id)) {
case 'shop_coupon':
mailchimp_get_api()->deletePromoRule(mailchimp_get_store_id(), $post_id);
mailchimp_log('promo_code.deleted', "deleted promo code {$post_id}");
break;
}
}
/**
* @param $post_id
*/
public function handlePostRestored($post_id)
{
if (!mailchimp_is_configured()) return;
switch(get_post_type($post_id)) {
case 'shop_coupon':
return $this->handleCouponRestored($post_id);
break;
}
}
/**
* @param $user_id
*/
public function handleUserRegistration($user_id)
{
if (!mailchimp_is_configured()) return;
$subscribed = (bool) isset($_POST['mailchimp_woocommerce_newsletter']) ?
$_POST['mailchimp_woocommerce_newsletter'] : false;
// update the user meta with the 'is_subscribed' form element
update_user_meta($user_id, 'mailchimp_woocommerce_is_subscribed', $subscribed);
if ($subscribed) {
wp_queue(new MailChimp_WooCommerce_User_Submit($user_id, $subscribed));
}
}
/**
* @param $user_id
* @param $old_user_data
*/
function handleUserUpdated($user_id, $old_user_data)
{
if (!mailchimp_is_configured()) return;
// only update this person if they were marked as subscribed before
$is_subscribed = get_user_meta($user_id, 'mailchimp_woocommerce_is_subscribed', true);
// if they don't have a meta set for is_subscribed, we will get a blank string, so just ignore this.
if ($is_subscribed === '' || $is_subscribed === null) return;
// only send this update if the user actually has a boolean value.
wp_queue(new MailChimp_WooCommerce_User_Submit($user_id, (bool) $is_subscribed, $old_user_data));
}
/**
* Delete all the options pointing to the pages, and re-start the sync process.
* @param bool $only_products
* @return bool
*/
protected function syncProducts($only_products = false)
{
if (!$this->isAdmin()) return false;
$this->removePointers(true, ($only_products ? false : true));
update_option('mailchimp-woocommerce-sync.orders.prevent', $only_products);
MailChimp_WooCommerce_Process_Products::push();
return true;
}
/**
* Delete all the options pointing to the pages, and re-start the sync process.
* @return bool
*/
protected function syncOrders()
{
if (!$this->isAdmin()) return false;
$this->removePointers(false, true);
// since the products are all good, let's sync up the orders now.
wp_queue(new MailChimp_WooCommerce_Process_Orders());
return true;
}
/**
* @return bool|string
*/
public function getCurrentUserEmail()
{
if (isset($this->user_email) && !empty($this->user_email)) {
return $this->user_email = strtolower($this->user_email);
}
$user = wp_get_current_user();
$email = ($user->ID > 0 && isset($user->user_email)) ? $user->user_email : $this->getEmailFromSession();
return $this->user_email = strtolower($email);
}
/**
* @return bool|array
*/
public function getCartItems()
{
if (!($this->cart = $this->getWooSession('cart', false))) {
$this->cart = function_exists('WC') ? false : WC()->cart->get_cart();
} else {
$cart_session = array();
foreach ( $this->cart as $key => $values ) {
$cart_session[$key] = $values;
unset($cart_session[$key]['data']); // Unset product object
}
return $this->cart = $cart_session;
}
return is_array($this->cart) ? $this->cart : false;
}
/**
* Set the cookie of the mailchimp campaigns if we have one.
*/
public function handleCampaignTracking()
{
// set the landing site cookie if we don't have one.
$this->setLandingSiteCookie();
$cookie_duration = $this->getCookieDuration();
// if we have a query string of the mc_cart_id in the URL, that means we are sending a campaign from MC
if (isset($_GET['mc_cart_id']) && !isset($_GET['removed_item'])) {
// try to pull the cart from the database.
if (($cart = $this->getCart($_GET['mc_cart_id'])) && !empty($cart)) {
// set the current user email
$this->user_email = trim(str_replace(' ','+', $cart->email));
if (($current_email = $this->getEmailFromSession()) && $current_email !== $this->user_email) {
$this->previous_email = $current_email;
@setcookie('mailchimp_user_previous_email',$this->user_email, $cookie_duration, '/' );
}
// cookie the current email
@setcookie('mailchimp_user_email', $this->user_email, $cookie_duration, '/' );
// set the cart data.
$this->setWooSession('cart', unserialize($cart->cart));
}
}
if (isset($_REQUEST['mc_cid'])) {
$this->setCampaignTrackingID($_REQUEST['mc_cid'], $cookie_duration);
}
if (isset($_REQUEST['mc_eid'])) {
@setcookie('mailchimp_email_id', trim($_REQUEST['mc_eid']), $cookie_duration, '/' );
}
}
/**
* @return mixed|null
*/
public function getCampaignTrackingID()
{
$cookie = $this->cookie('mailchimp_campaign_id', false);
if (empty($cookie)) {
$cookie = $this->getWooSession('mailchimp_tracking_id', false);
}
return $cookie;
}
/**
* @param $id
* @param $cookie_duration
* @return $this
*/
public function setCampaignTrackingID($id, $cookie_duration)
{
$cid = trim($id);
@setcookie('mailchimp_campaign_id', $cid, $cookie_duration, '/' );
$this->setWooSession('mailchimp_campaign_id', $cid);
return $this;
}
/**
* @return mixed|null
*/
public function getLandingSiteCookie()
{
$cookie = $this->cookie('mailchimp_landing_site', false);
if (empty($cookie)) {
$cookie = $this->getWooSession('mailchimp_landing_site', false);
}
return $cookie;
}
/**
* @return $this
*/
public function setLandingSiteCookie()
{
if (isset($_GET['expire_landing_site'])) $this->expireLandingSiteCookie();
// if we already have a cookie here, we need to skip it.
if ($this->getLandingSiteCookie() != false) return $this;
$http_referer = $this->getReferer();
if (!empty($http_referer)) {
// grab the current landing url since it's a referral.
$landing_site = home_url() . wp_unslash($_SERVER['REQUEST_URI']);
$compare_refer = str_replace(array('http://', 'https://'), '', $http_referer);
$compare_local = str_replace(array('http://', 'https://'), '', $landing_site);
if (strpos($compare_local, $compare_refer) === 0) return $this;
// set the cookie
@setcookie('mailchimp_landing_site', $landing_site, $this->getCookieDuration(), '/' );
$this->setWooSession('mailchimp_landing_site', $landing_site);
}
return $this;
}
/**
* @return array|bool|string
*/
public function getReferer()
{
if (!empty($_REQUEST['_wp_http_referer'])) {
return wp_unslash($_REQUEST['_wp_http_referer']);
} elseif (!empty($_SERVER['HTTP_REFERER'])) {
return wp_unslash( $_SERVER['HTTP_REFERER']);
}
return false;
}
/**
* @return $this
*/
public function expireLandingSiteCookie()
{
@setcookie('mailchimp_landing_site', false, $this->getCookieDuration(), '/' );
$this->setWooSession('mailchimp_landing_site', false);
return $this;
}
/**
* @return bool
*/
protected function getEmailFromSession()
{
return $this->cookie('mailchimp_user_email', false);
}
/**
* @return bool
*/
protected function getPreviousEmailFromSession()
{
if ($this->previous_email) {
return $this->previous_email = strtolower($this->previous_email);
}
$email = $this->cookie('mailchimp_user_previous_email', false);
return $email ? strtolower($email) : false;
}
/**
* @param $key
* @param null $default
* @return mixed|null
*/
public function getWooSession($key, $default = null)
{
if (!function_exists('WC')) return $default;
if (!($woo = WC()) || empty($woo->session)) {
return $default;
}
return $woo->session->get($key, $default);
}
/**
* @param $key
* @param $value
* @return $this
*/
public function setWooSession($key, $value)
{
if (!function_exists('WC')) return $this;
if (!($woo = WC()) || empty($woo->session)) {
return $this;
}
$woo->session->set($key, $value);
return $this;
}
/**
* @param $key
* @return $this
*/
public function removeWooSession($key)
{
if (!function_exists('WC')) return $this;
if (!($woo = WC()) || empty($woo->session)) {
return $this;
}
$woo->session->__unset($key);
return $this;
}
/**
*
*/
public function get_user_by_hash()
{
if ($this->doingAjax() && isset($_GET['hash'])) {
if (($cart = $this->getCart($_GET['hash']))) {
$this->respondJSON(array('success' => true, 'email' => $cart->email));
}
}
$this->respondJSON(array('success' => false, 'email' => false));
}
/**
*
*/
public function set_user_by_email()
{
if ($this->is_admin) {
$this->respondJSON(array('success' => false));
}
if ($this->doingAjax() && isset($_GET['email'])) {
$cookie_duration = $this->getCookieDuration();
$this->user_email = trim(str_replace(' ','+', $_GET['email']));
if (($current_email = $this->getEmailFromSession()) && $current_email !== $this->user_email) {
$this->previous_email = $current_email;
$this->force_cart_post = true;
@setcookie('mailchimp_user_previous_email',$this->user_email, $cookie_duration, '/' );
}
@setcookie('mailchimp_user_email', $this->user_email, $cookie_duration, '/' );
$this->getCartItems();
$this->handleCartUpdated();
$this->respondJSON(array(
'success' => true,
'email' => $this->user_email,
'previous' => $this->previous_email,
'cart' => $this->cart,
));
}
$this->respondJSON(array('success' => false, 'email' => false));
}
/**
* @param string $time
* @return int
*/
protected function getCookieDuration($time = 'thirty_days')
{
$durations = array(
'one_day' => 86400, 'seven_days' => 604800, 'fourteen_days' => 1209600, 'thirty_days' => 2419200,
);
if (!array_key_exists($time, $durations)) {
$time = 'thirty_days';
}
return time() + $durations[$time];
}
/**
* @param $key
* @param bool $default
* @return bool
*/
protected function get($key, $default = false)
{
if (!isset($_REQUEST['mailchimp-woocommerce']) || !isset($_REQUEST['mailchimp-woocommerce'][$key])) {
return $default;
}
return $_REQUEST['mailchimp-woocommerce'][$key];
}
/**
* @param $uid
* @return array|bool|null|object|void
*/
protected function getCart($uid)
{
if (!$this->validated_cart_db) return false;
global $wpdb;
$table = "{$wpdb->prefix}mailchimp_carts";
$statement = "SELECT * FROM $table WHERE id = %s";
$sql = $wpdb->prepare($statement, $uid);
if (($saved_cart = $wpdb->get_row($sql)) && !empty($saved_cart)) {
return $saved_cart;
}
return false;
}
/**
* @param $uid
* @return true
*/
protected function deleteCart($uid)
{
if (!$this->validated_cart_db) return false;
global $wpdb;
$table = "{$wpdb->prefix}mailchimp_carts";
$sql = $wpdb->prepare("DELETE FROM $table WHERE id = %s", $uid);
$wpdb->query($sql);
return true;
}
/**
* @param $uid
* @param $email
* @return bool
*/
protected function trackCart($uid, $email)
{
if (!$this->validated_cart_db) return false;
global $wpdb;
$table = "{$wpdb->prefix}mailchimp_carts";
$statement = "SELECT * FROM $table WHERE id = %s";
$sql = $wpdb->prepare($statement, $uid);
$user_id = get_current_user_id();
if (($saved_cart = $wpdb->get_row($sql)) && is_object($saved_cart)) {
$statement = "UPDATE {$table} SET `cart` = '%s', `email` = '%s', `user_id` = %s WHERE `id` = '%s'";
$sql = $wpdb->prepare($statement, array(maybe_serialize($this->cart), $email, $user_id, $uid));
$wpdb->query($sql);
} else {
$wpdb->insert("{$wpdb->prefix}mailchimp_carts", array(
'id' => $uid,
'email' => $email,
'user_id' => (int) $user_id,
'cart' => maybe_serialize($this->cart),
'created_at' => gmdate('Y-m-d H:i:s', time()),
));
}
return true;
}
/**
* @param $data
*/
protected function respondJSON($data)
{
header('Content-Type: application/json');
echo json_encode($data);
exit;
}
}

View File

@@ -0,0 +1,443 @@
<?php
/**
* The file that defines the core plugin class
*
* A class definition that includes attributes and functions used across both the
* public-facing side of the site and the admin area.
*
* @link https://mailchimp.com
* @since 1.0.1
*
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
*/
/**
* The core plugin class.
*
* This is used to define internationalization, admin-specific hooks, and
* public-facing site hooks.
*
* Also maintains the unique identifier of this plugin as well as the current
* version of the plugin.
*
* @since 1.0.0
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
* @author Ryan Hungate <ryan@vextras.com>
*/
class MailChimp_WooCommerce {
/**
* The loader that's responsible for maintaining and registering all hooks that power
* the plugin.
*
* @since 1.0.0
* @access protected
* @var MailChimp_WooCommerce_Loader $loader Maintains and registers all hooks for the plugin.
*/
protected $loader;
/**
* The unique identifier of this plugin.
*
* @since 1.0.0
* @access protected
* @var string $plugin_name The string used to uniquely identify this plugin.
*/
protected $plugin_name;
/**
* The current version of the plugin.
*
* @since 1.0.0
* @access protected
* @var string $version The current version of the plugin.
*/
protected $version;
/**
* @var string
*/
protected $environment = 'production';
protected static $logging_config = null;
/**
* @return object
*/
public static function getLoggingConfig()
{
if (is_object(static::$logging_config)) {
return static::$logging_config;
}
$plugin_options = get_option('mailchimp-woocommerce');
$is_options = is_array($plugin_options);
$api_key = $is_options && array_key_exists('mailchimp_api_key', $plugin_options) ?
$plugin_options['mailchimp_api_key'] : false;
$enable_logging = $is_options &&
array_key_exists('mailchimp_debugging', $plugin_options) &&
$plugin_options['mailchimp_debugging'];
$account_id = $is_options && array_key_exists('mailchimp_account_info_id', $plugin_options) ?
$plugin_options['mailchimp_account_info_id'] : false;
$username = $is_options && array_key_exists('mailchimp_account_info_username', $plugin_options) ?
$plugin_options['mailchimp_account_info_username'] : false;
$api_key_parts = str_getcsv($api_key, '-');
$data_center = isset($api_key_parts[1]) ? $api_key_parts[1] : 'us1';
return static::$logging_config = (object) array(
'enable_logging' => (bool) $enable_logging,
'account_id' => $account_id,
'username' => $username,
'endpoint' => 'https://ecommerce.'.$data_center.'.list-manage.com/ecommerce/log',
);
}
/**
* Define the core functionality of the plugin.
*
* Set the plugin name and the plugin version that can be used throughout the plugin.
* Load the dependencies, define the locale, and set the hooks for the admin area and
* the public-facing side of the site.
*
* @param string $environment
* @param string $version
*
* @since 1.0.0
*/
public function __construct($environment = 'production', $version = '1.0.0') {
$this->plugin_name = 'mailchimp-woocommerce';
$this->version = $version;
$this->environment = $environment;
$this->load_dependencies();
$this->set_locale();
$this->define_admin_hooks();
$this->define_public_hooks();
$this->activateMailChimpNewsletter();
$this->activateMailChimpService();
}
/**
* Load the required dependencies for this plugin.
*
* Include the following files that make up the plugin:
*
* - MailChimp_WooCommerce_Loader. Orchestrates the hooks of the plugin.
* - MailChimp_WooCommerce_i18n. Defines internationalization functionality.
* - MailChimp_WooCommerce_Admin. Defines all hooks for the admin area.
* - MailChimp_WooCommerce_Public. Defines all hooks for the public side of the site.
*
* Create an instance of the loader which will be used to register the hooks
* with WordPress.
*
* @since 1.0.0
* @access private
*/
private function load_dependencies() {
global $wp_queue;
if (empty($wp_queue)) {
$wp_queue = new WP_Queue();
}
// fire up the loader
$this->loader = new MailChimp_WooCommerce_Loader();
if (!mailchimp_running_in_console() && mailchimp_is_configured()) {
// fire up the http worker container
new WP_Http_Worker($wp_queue);
}
// if we're not running in the console, and the http_worker is not running
if (mailchimp_should_init_queue()) {
try {
// if we do not have a site transient for the queue listener
if (!get_site_transient('http_worker_queue_listen')) {
// set the site transient to expire in 50 seconds so this will not happen too many times
// but still work for cron scripts on the minute mark.
set_site_transient( 'http_worker_queue_listen', microtime(), 50);
// if we have available jobs, call the http worker manually
if ($wp_queue->available_jobs()) {
mailchimp_call_http_worker_manually();
}
}
} catch (\Exception $e) {}
}
}
/**
* Define the locale for this plugin for internationalization.
*
* Uses the MailChimp_WooCommerce_i18n class in order to set the domain and to register the hook
* with WordPress.
*
* @since 1.0.0
* @access private
*/
private function set_locale() {
$plugin_i18n = new MailChimp_WooCommerce_i18n();
$this->loader->add_action( 'plugins_loaded', $plugin_i18n, 'load_plugin_textdomain' );
}
/**
* Register all of the hooks related to the admin area functionality
* of the plugin.
*
* @since 1.0.0
* @access private
*/
private function define_admin_hooks() {
$plugin_admin = new MailChimp_WooCommerce_Admin( $this->get_plugin_name(), $this->get_version() );
$this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_styles');
$this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts');
// Add menu item
$this->loader->add_action('admin_menu', $plugin_admin, 'add_plugin_admin_menu');
// Add Settings link to the plugin
$plugin_basename = plugin_basename( plugin_dir_path( __DIR__ ) . $this->plugin_name . '.php');
$this->loader->add_filter('plugin_action_links_' . $plugin_basename, $plugin_admin, 'add_action_links');
// make sure we're listening for the admin init
$this->loader->add_action('admin_init', $plugin_admin, 'options_update');
// put the menu on the admin top bar.
//$this->loader->add_action('admin_bar_menu', $plugin_admin, 'admin_bar', 100);
$this->loader->add_action('plugins_loaded', $plugin_admin, 'update_db_check');
}
/**
* Register all of the hooks related to the public-facing functionality
* of the plugin.
*
* @since 1.0.0
* @access private
*/
private function define_public_hooks() {
$plugin_public = new MailChimp_WooCommerce_Public( $this->get_plugin_name(), $this->get_version() );
$this->loader->add_action('wp_enqueue_scripts', $plugin_public, 'enqueue_styles');
$this->loader->add_action('wp_enqueue_scripts', $plugin_public, 'enqueue_scripts');
}
/**
* Handle the newsletter actions here.
*/
private function activateMailChimpNewsletter()
{
$service = new MailChimp_Newsletter();
if ($service->isConfigured()) {
$service->setEnvironment($this->environment);
$service->setVersion($this->version);
// adding the ability to render the checkbox on another screen of the checkout page.
$render_on = $service->getOption('mailchimp_checkbox_action', 'woocommerce_after_checkout_billing_form');
$this->loader->add_action($render_on, $service, 'applyNewsletterField', 10);
$this->loader->add_action('woocommerce_ppe_checkout_order_review', $service, 'applyNewsletterField', 10);
$this->loader->add_action('woocommerce_register_form', $service, 'applyNewsletterField', 10);
$this->loader->add_action('woocommerce_checkout_order_processed', $service, 'processNewsletterField', 10, 2);
$this->loader->add_action('woocommerce_ppe_do_payaction', $service, 'processPayPalNewsletterField', 10, 1);
$this->loader->add_action('woocommerce_register_post', $service, 'processRegistrationForm', 10, 3);
}
}
/**
* Handle all the service hooks here.
*/
private function activateMailChimpService()
{
$service = new MailChimp_Service();
if ($service->isConfigured()) {
$service->setEnvironment($this->environment);
$service->setVersion($this->version);
// core hook setup
$this->loader->add_action('admin_init', $service, 'adminReady');
$this->loader->add_action('woocommerce_init', $service, 'wooIsRunning');
// for the data sync we need to configure basic auth.
$this->loader->add_filter('http_request_args', $service, 'addHttpRequestArgs', 10, 2);
// campaign tracking
$this->loader->add_action( 'init', $service, 'handleCampaignTracking' );
// order hooks
$this->loader->add_action('woocommerce_thankyou', $service, 'onNewOrder', 10);
$this->loader->add_action('woocommerce_api_create_order', $service, 'onNewOrder', 10);
$this->loader->add_action('woocommerce_ppe_do_payaction', $service, 'onNewPayPalOrder', 10, 1);
$this->loader->add_action('woocommerce_order_status_changed', $service, 'handleOrderStatusChanged', 10);
// partially refunded
$this->loader->add_action('woocommerce_order_partially_refunded', $service, 'onPartiallyRefunded', 10);
// cart hooks
//$this->loader->add_action('woocommerce_cart_updated', $service, 'handleCartUpdated');
$this->loader->add_filter('woocommerce_update_cart_action_cart_updated', $service, 'handleCartUpdated');
$this->loader->add_action('woocommerce_add_to_cart', $service, 'handleCartUpdated');
$this->loader->add_action('woocommerce_cart_item_removed', $service, 'handleCartUpdated');
// save post hooks
$this->loader->add_action('save_post', $service, 'handlePostSaved', 10, 3);
$this->loader->add_action('wp_trash_post', $service, 'handlePostTrashed', 10);
$this->loader->add_action('untrashed_post', $service, 'handlePostRestored', 10);
//coupons
$this->loader->add_action('woocommerce_new_coupon', $service, 'handleNewCoupon', 10);
$this->loader->add_action('woocommerce_coupon_options_save', $service, 'handleCouponSaved', 10, 2);
$this->loader->add_action('woocommerce_api_create_coupon', $service, 'handleCouponSaved', 9, 2);
$this->loader->add_action('woocommerce_delete_coupon', $service, 'handleCouponTrashed', 10);
$this->loader->add_action('woocommerce_trash_coupon', $service, 'handleCouponTrashed', 10);
$this->loader->add_action('woocommerce_api_delete_coupon', $service, 'handleCouponTrashed', 9);
// handle the user registration hook
$this->loader->add_action('user_register', $service, 'handleUserRegistration');
// handle the user updated profile hook
$this->loader->add_action('profile_update', $service, 'handleUserUpdated', 10, 2);
// when someone deletes a user??
//$this->loader->add_action('delete_user', $service, 'handleUserDeleting');
$this->loader->add_action('wp_ajax_nopriv_mailchimp_get_user_by_hash', $service, 'get_user_by_hash');
$this->loader->add_action('wp_ajax_nopriv_mailchimp_set_user_by_email', $service, 'set_user_by_email');
}
}
/**
* Run the loader to execute all of the hooks with WordPress.
*
* @since 1.0.0
*/
public function run() {
$this->loader->run();
}
/**
* The name of the plugin used to uniquely identify it within the context of
* WordPress and to define internationalization functionality.
*
* @since 1.0.1
* @return string The name of the plugin.
*/
public function get_plugin_name() {
return $this->plugin_name;
}
/**
* The reference to the class that orchestrates the hooks with the plugin.
*
* @since 1.0.1
* @return MailChimp_WooCommerce_Loader Orchestrates the hooks of the plugin.
*/
public function get_loader() {
return $this->loader;
}
/**
* Retrieve the version number of the plugin.
*
* @since 1.0.1
* @return string The version number of the plugin.
*/
public function get_version() {
return $this->version;
}
/**
* This is just in case we ever needed to revert back to the old loading
*/
protected function manual_file_loader()
{
$path = plugin_dir_path(dirname( __FILE__ ));
/** The abstract options class.*/
require_once $path . 'includes/class-mailchimp-woocommerce-options.php';
/** The class responsible for orchestrating the actions and filters of the core plugin.*/
require_once $path . 'includes/class-mailchimp-woocommerce-loader.php';
/** The class responsible for defining internationalization functionality of the plugin. */
require_once $path . 'includes/class-mailchimp-woocommerce-i18n.php';
/** The service class.*/
require_once $path . 'includes/class-mailchimp-woocommerce-service.php';
/** The newsletter class. */
require_once $path . 'includes/class-mailchimp-woocommerce-newsletter.php';
/** The class responsible for defining all actions that occur in the admin area.*/
require_once $path . 'admin/class-mailchimp-woocommerce-admin.php';
/** The class responsible for defining all actions that occur in the public-facing side of the site. */
require_once $path . 'public/class-mailchimp-woocommerce-public.php';
/** Require all the MailChimp Assets for the API */
require_once $path . 'includes/api/class-mailchimp-api.php';
require_once $path . 'includes/api/class-mailchimp-woocommerce-api.php';
require_once $path . 'includes/api/class-mailchimp-woocommerce-create-list-submission.php';
require_once $path . 'includes/api/class-mailchimp-woocommerce-transform-orders-wc3.php';
require_once $path . 'includes/api/class-mailchimp-woocommerce-transform-products.php';
require_once $path . 'includes/api/class-mailchimp-woocommerce-transform-coupons.php';
/** Require all the mailchimp api asset classes */
require_once $path . 'includes/api/assets/class-mailchimp-address.php';
require_once $path . 'includes/api/assets/class-mailchimp-cart.php';
require_once $path . 'includes/api/assets/class-mailchimp-customer.php';
require_once $path . 'includes/api/assets/class-mailchimp-line-item.php';
require_once $path . 'includes/api/assets/class-mailchimp-order.php';
require_once $path . 'includes/api/assets/class-mailchimp-product.php';
require_once $path . 'includes/api/assets/class-mailchimp-product-variation.php';
require_once $path . 'includes/api/assets/class-mailchimp-store.php';
require_once $path . 'includes/api/assets/class-mailchimp-promo-code.php';
require_once $path . 'includes/api/assets/class-mailchimp-promo-rule.php';
/** Require all the api error helpers */
require_once $path . 'includes/api/errors/class-mailchimp-error.php';
require_once $path . 'includes/api/errors/class-mailchimp-server-error.php';
/** Require the various helper scripts */
require_once $path . 'includes/api/helpers/class-mailchimp-woocommerce-api-currency-codes.php';
require_once $path . 'includes/api/helpers/class-mailchimp-woocommerce-api-locales.php';
/** Background job sync tools */
// make sure the queue exists first since the other files depend on it.
require_once $path . 'includes/vendor/queue.php';
// the abstract bulk sync class
require_once $path.'includes/processes/class-mailchimp-woocommerce-abstract-sync.php';
// bulk data sync
require_once $path.'includes/processes/class-mailchimp-woocommerce-process-orders.php';
require_once $path.'includes/processes/class-mailchimp-woocommerce-process-products.php';
require_once $path.'includes/processes/class-mailchimp-woocommerce-process-coupons.php';
// individual item sync
require_once $path.'includes/processes/class-mailchimp-woocommerce-cart-update.php';
require_once $path.'includes/processes/class-mailchimp-woocommerce-single-order.php';
require_once $path.'includes/processes/class-mailchimp-woocommerce-single-product.php';
require_once $path.'includes/processes/class-mailchimp-woocommerce-single-coupon.php';
require_once $path.'includes/processes/class-mailchimp-woocommerce-user-submit.php';
}
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden

View File

@@ -0,0 +1,395 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/14/16
* Time: 11:54 AM
*/
abstract class MailChimp_WooCommerce_Abstract_Sync extends WP_Job
{
/**
* @var MailChimp_WooCommerce_Api
*/
private $api;
/**
* @var MailChimp_WooCommerce_MailChimpApi
*/
private $mc;
/**
* @var string
*/
private $plugin_name = 'mailchimp-woocommerce';
/**
* @var string
*/
protected $store_id = '';
/**
* @return mixed
*/
abstract public function getResourceType();
/**
* @param $item
* @return mixed
*/
abstract protected function iterate($item);
/**
* @return mixed
*/
abstract protected function complete();
/**
* @return mixed
*/
public function go()
{
return $this->handle();
}
/**
* @return string
*/
public function getStoreID()
{
return mailchimp_get_store_id();
}
/**
* Task
*
* Override this method to perform any actions required on each
* queue item. Return the modified item for further processing
* in the next pass through. Or, return false to remove the
* item from the queue.
*
* @param mixed $item Queue item to iterate over
*
* @return mixed
*/
public function handle()
{
global $wpdb;
if (!mailchimp_is_configured()) {
mailchimp_debug(get_called_class(), 'mailchimp is not configured properly');
return false;
}
if (!($this->store_id = $this->getStoreID())) {
mailchimp_debug(get_called_class().'@handle', 'store id not loaded');
$this->delete();
return false;
}
// don't let recursion happen.
if ($this->getResourceType() === 'orders' && $this->getResourceCompleteTime()) {
mailchimp_log('sync.stop', "halting the sync for :: {$this->getResourceType()}");
$this->delete();
return false;
}
$page = $this->getResources();
if (empty($page)) {
mailchimp_debug(get_called_class().'@handle', 'could not find any more '.$this->getResourceType().' records ending on page '.$this->getResourcePagePointer());
// call the completed event to process further
$this->resourceComplete($this->getResourceType());
$this->complete();
$this->delete();
return false;
}
$this->setResourcePagePointer(($page->page + 1), $this->getResourceType());
// if we've got a 0 count, that means we're done.
if ($page->count <= 0) {
mailchimp_debug(get_called_class().'@handle', $this->getResourceType().' :: completing now!');
// reset the resource page back to 1
$this->resourceComplete($this->getResourceType());
// call the completed event to process further
$this->complete();
$this->delete();
return false;
}
// iterate through the items and send each one through the pipeline based on this class.
foreach ($page->items as $resource) {
$this->iterate($resource);
}
$this->delete();
$class_name = get_called_class();
$wpdb->query("DELETE FROM {$wpdb->prefix}queue WHERE job LIKE '%{$class_name}%'");
// this will paginate through all records for the resource type until they return no records.
wp_queue(new static());
mailchimp_debug(get_called_class().'@handle', 'queuing up the next job');
return false;
}
/**
* @return $this
*/
public function flagStartSync()
{
$job = new MailChimp_Service();
$job->removeSyncPointers();
$this->setData('sync.config.resync', false);
$this->setData('sync.orders.current_page', 1);
$this->setData('sync.products.current_page', 1);
$this->setData('sync.syncing', true);
$this->setData('sync.started_at', time());
global $wpdb;
try {
$wpdb->show_errors(false);
$wpdb->query("DELETE FROM {$wpdb->prefix}queue");
$wpdb->show_errors(true);
} catch (\Exception $e) {}
mailchimp_log('sync.started', "Starting Sync :: ".date('D, M j, Y g:i A'));
// flag the store as syncing
mailchimp_get_api()->flagStoreSync(mailchimp_get_store_id(), true);
return $this;
}
/**
* @return $this
*/
public function flagStopSync()
{
// this is the last thing we're doing so it's complete as of now.
$this->setData('sync.syncing', false);
$this->setData('sync.completed_at', time());
// set the current sync pages back to 1 if the user hits resync.
$this->setData('sync.orders.current_page', 1);
$this->setData('sync.products.current_page', 1);
mailchimp_log('sync.completed', "Finished Sync :: ".date('D, M j, Y g:i A'));
// flag the store as sync_finished
mailchimp_get_api()->flagStoreSync(mailchimp_get_store_id(), false);
return $this;
}
/**
* @return bool|object|stdClass
*/
public function getResources()
{
$current_page = $this->getResourcePagePointer($this->getResourceType());
if ($current_page === 'complete') {
if (!$this->getData('sync.config.resync', false)) {
return false;
}
$current_page = 1;
$this->setResourcePagePointer($current_page);
$this->setData('sync.config.resync', false);
}
return $this->api()->paginate($this->getResourceType(), $current_page, 5);
}
/**
* @param null|string $resource
* @return $this
*/
public function resetResourcePagePointer($resource = null)
{
if (empty($resource)) $resource = $this->getResourceType();
$this->setData('sync.'.$resource.'.current_page', 1);
return $this;
}
/**
* @param null|string $resource
* @return null
*/
public function getResourcePagePointer($resource = null)
{
if (empty($resource)) $resource = $this->getResourceType();
return $this->getData('sync.'.$resource.'.current_page', 1);
}
/**
* @param $page
* @param null $resource
* @return MailChimp_WooCommerce_Abstract_Sync
*/
public function setResourcePagePointer($page, $resource = null)
{
if (empty($resource)) $resource = $this->getResourceType();
return $this->setData('sync.'.$resource.'.current_page', $page);
}
/**
* @param null|string $resource
* @return $this
*/
protected function resourceComplete($resource = null)
{
if (empty($resource)) $resource = $this->getResourceType();
$this->setData('sync.'.$resource.'.current_page', 'complete');
return $this;
}
/**
* @return null
*/
protected function setResourceCompleteTime($resource = null)
{
if (empty($resource)) $resource = $this->getResourceType();
return $this->setData('sync.'.$resource.'.completed_at', time());
}
/**
* @param null $resource
* @return bool|DateTime
*/
protected function getResourceCompleteTime($resource = null)
{
if (empty($resource)) $resource = $this->getResourceType();
$time = $this->getData('sync.'.$resource.'.completed_at', false);
if ($time > 0) {
try {
$date = new \DateTime();
$date->setTimestamp($time);
return $date;
} catch (\Exception $e) {
return false;
}
}
return false;
}
/**
* @param $key
* @param null $default
* @return null
*/
public function getOption($key, $default = null)
{
$options = $this->getOptions();
if (isset($options[$key])) {
return $options[$key];
}
return $default;
}
/**
* @param $key
* @param $value
* @return $this
*/
public function setOption($key, $value)
{
$options = $this->getOptions();
$options[$key] = $value;
update_option($this->plugin_name, $options);
return $this;
}
/**
* @param $key
* @param bool $default
* @return bool
*/
public function hasOption($key, $default = false)
{
return (bool) $this->getOption($key, $default);
}
/**
* @return array
*/
public function getOptions()
{
$options = get_option($this->plugin_name);
return is_array($options) ? $options : array();
}
/**
* @param $key
* @param $value
* @return $this
*/
public function setData($key, $value)
{
update_option($this->plugin_name.'-'.$key, $value, 'yes');
return $this;
}
/**
* @param $key
* @param null $default
* @return mixed|void
*/
public function getData($key, $default = null)
{
return get_option($this->plugin_name.'-'.$key, $default);
}
/**
* @param $key
* @return bool
*/
public function removeData($key)
{
return delete_option($this->plugin_name.'-'.$key);
}
/**
* @return MailChimp_WooCommerce_Api
*/
protected function api()
{
if (empty($this->api)) {
$this->api = new MailChimp_WooCommerce_Api();
}
return $this->api;
}
/**
* @return MailChimp_WooCommerce_MailChimpApi
*/
protected function mailchimp()
{
if (empty($this->mc)) {
$this->mc = new MailChimp_WooCommerce_MailChimpApi($this->getOption('mailchimp_api_key'));
}
return $this->mc;
}
}

View File

@@ -0,0 +1,182 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/15/16
* Time: 11:42 AM
*/
class MailChimp_WooCommerce_Cart_Update extends WP_Job
{
public $unique_id;
public $email;
public $previous_email;
public $campaign_id;
public $cart_data;
public $ip_address;
/**
* MailChimp_WooCommerce_Cart_Update constructor.
* @param null $uid
* @param null $email
* @param null $campaign_id
* @param array $cart_data
*/
public function __construct($uid = null, $email = null, $campaign_id = null, array $cart_data = array())
{
if ($uid) {
$this->unique_id = $uid;
}
if ($email) {
$this->email = $email;
}
if (!empty($cart_data)) {
$this->cart_data = json_encode($cart_data);
}
if ($campaign_id) {
$this->campaign_id = $campaign_id;
}
$this->ip_address = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null;
}
/**
* @return bool
*/
public function handle()
{
if (($result = $this->process())) {
mailchimp_log('ac.success', 'Added', array('api_response' => $result->toArray()));
}
return false;
}
/**
* @return bool|MailChimp_WooCommerce_Cart
*/
public function process()
{
try {
if (!mailchimp_is_configured() || !($api = mailchimp_get_api())) {
mailchimp_debug(get_called_class(), 'mailchimp is not configured properly');
return false;
}
$options = get_option('mailchimp-woocommerce', array());
$store_id = mailchimp_get_store_id();
$this->cart_data = json_decode($this->cart_data, true);
// delete it and the add it back.
$api->deleteCartByID($store_id, $this->unique_id);
// if they emptied the cart ignore it.
if (!is_array($this->cart_data) || empty($this->cart_data)) {
return false;
}
$checkout_url = wc_get_checkout_url();
if (mailchimp_string_contains($checkout_url, '?')) {
$checkout_url .= '&mc_cart_id='.$this->unique_id;
} else {
$checkout_url .= '?mc_cart_id='.$this->unique_id;
}
$customer = new MailChimp_WooCommerce_Customer();
$customer->setId($this->unique_id);
$customer->setEmailAddress($this->email);
$customer->setOptInStatus(false);
$cart = new MailChimp_WooCommerce_Cart();
$cart->setId($this->unique_id);
$cart->setCampaignID($this->campaign_id);
$cart->setCheckoutUrl($checkout_url);
$cart->setCurrencyCode(isset($options['store_currency_code']) ? $options['store_currency_code'] : 'USD');
$cart->setCustomer($customer);
$order_total = 0;
$products = array();
foreach ($this->cart_data as $hash => $item) {
try {
$line = $this->transformLineItem($hash, $item);
$cart->addItem($line);
$order_total += ($item['quantity'] * $line->getPrice());
$products[] = $line;
} catch (\Exception $e) {}
}
if (empty($products)) {
return false;
}
$cart->setOrderTotal($order_total);
try {
// if the post is successful we're all good.
$api->addCart($store_id, $cart, false);
mailchimp_log('abandoned_cart.success', "email: {$customer->getEmailAddress()} :: checkout_url: $checkout_url");
} catch (\Exception $e) {
mailchimp_error('abandoned_cart.error', "email: {$customer->getEmailAddress()} :: attempting product update :: {$e->getMessage()}");
// if we have an error it's most likely due to a product not being found.
// let's loop through each item, verify that we have the product or not.
// if not, we will add it.
foreach ($products as $item) {
/** @var MailChimp_WooCommerce_LineItem $item */
$transformer = new MailChimp_WooCommerce_Single_Product($item->getProductID());
if (!$transformer->api()->getStoreProduct($store_id, $item->getProductId())) {
$transformer->handle();
}
}
// if the post is successful we're all good.
$api->addCart($store_id, $cart, false);
mailchimp_log('abandoned_cart.success', "email: {$customer->getEmailAddress()}");
}
} catch (\Exception $e) {
update_option('mailchimp-woocommerce-cart-error', $e->getMessage());
mailchimp_error('abandoned_cart.error', $e);
}
return false;
}
/**
* @param string $hash
* @param $item
* @return MailChimp_WooCommerce_LineItem
*/
protected function transformLineItem($hash, $item)
{
$product = wc_get_product($item['product_id']);
$price = $product ? $product->get_price() : 0;
$line = new MailChimp_WooCommerce_LineItem();
$line->setId($hash);
$line->setProductId($item['product_id']);
if (isset($item['variation_id']) && $item['variation_id'] > 0) {
$line->setProductVariantId($item['variation_id']);
} else {
$line->setProductVariantId($item['product_id']);
}
$line->setQuantity($item['quantity']);
$line->setPrice($price);
return $line;
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 10/06/17
* Time: 10:57 AM
*/
class MailChimp_WooCommerce_Process_Coupons extends MailChimp_WooCommerce_Abstract_Sync
{
/**
* @var string
*/
protected $action = 'mailchimp_woocommerce_process_coupons';
/**
* @return string
*/
public function getResourceType()
{
return 'coupons';
}
/**
* @param WC_Coupon $item
*
* @return mixed
*/
protected function iterate($item)
{
if ($item instanceof MailChimp_WooCommerce_PromoCode) {
mailchimp_debug('promo_code_sync', "#{$item->getId()}", $item->toArray());
try {
$this->mailchimp()->addPromoRule($this->store_id, $item->getAttachedPromoRule(), true);
$response = $this->mailchimp()->addPromoCodeForRule($this->store_id, $item->getAttachedPromoRule(), $item, true);
mailchimp_log('coupon_sync.success', "update promo rule :: #{$item->getCode()}");
return $response;
} catch (MailChimp_WooCommerce_ServerError $e) {
mailchimp_error('order_submit.error', mailchimp_error_trace($e, "update promo rule :: {$item->getCode()}"));
return false;
} catch (MailChimp_WooCommerce_Error $e) {
mailchimp_error('order_submit.error', mailchimp_error_trace($e, "update promo rule :: {$item->getCode()}"));
return false;
} catch (Exception $e) {
mailchimp_error('order_submit.error', mailchimp_error_trace($e, "update promo rule :: {$item->getCode()}"));
return false;
}
}
mailchimp_debug('coupon_sync', 'no coupon found', $item);
return false;
}
/**
* After the resources have been loaded and pushed
*/
protected function complete()
{
mailchimp_log('coupon_sync.completed', 'Done with the coupon sync.');
// add a timestamp for the orders sync completion
$this->setResourceCompleteTime();
}
}

View File

@@ -0,0 +1,104 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/14/16
* Time: 10:57 AM
*/
class MailChimp_WooCommerce_Process_Orders extends MailChimp_WooCommerce_Abstract_Sync
{
/**
* @var string
*/
protected $action = 'mailchimp_woocommerce_process_orders';
public $items = array();
/**
* @return string
*/
public function getResourceType()
{
return 'orders';
}
/**
* @param MailChimp_WooCommerce_Order $item
*
* @return mixed
*/
protected function iterate($item)
{
if ($item instanceof MailChimp_WooCommerce_Order) {
// since we're syncing the customer for the first time, this is where we need to add the override
// for subscriber status. We don't get the checkbox until this plugin is actually installed and working!
if (!($status = $item->getCustomer()->getOptInStatus())) {
try {
$subscriber = $this->mailchimp()->member(mailchimp_get_list_id(), $item->getCustomer()->getEmailAddress());
$status = !in_array($subscriber['status'], array('unsubscribed', 'transactional'));
} catch (\Exception $e) {
$status = (bool) $this->getOption('mailchimp_auto_subscribe', true);
}
$item->getCustomer()->setOptInStatus($status);
}
mailchimp_debug('order_sync', "#{$item->getId()}", $item->toArray());
$type = $this->mailchimp()->getStoreOrder($this->store_id, $item->getId()) ? 'update' : 'create';
$call = $type === 'create' ? 'addStoreOrder' : 'updateStoreOrder';
try {
// if the order is in failed or cancelled status - and it's brand new, we shouldn't submit it.
if ($call === 'addStoreOrder' && in_array($item->getFinancialStatus(), array('failed', 'cancelled'))) {
return false;
}
// make the call
$response = $this->mailchimp()->$call($this->store_id, $item, false);
if (empty($response)) {
mailchimp_error('order_submit.failure', "$call :: #{$item->getId()} :: email: {$item->getCustomer()->getEmailAddress()} produced a blank response from MailChimp");
return $response;
}
mailchimp_log('order_submit.success', "$call :: #{$item->getId()} :: email: {$item->getCustomer()->getEmailAddress()}");
$this->items[] = array('response' => $response, 'item' => $item);
return $response;
} catch (MailChimp_WooCommerce_ServerError $e) {
mailchimp_error('order_submit.error', mailchimp_error_trace($e, "$call :: {$item->getId()}"));
return false;
} catch (MailChimp_WooCommerce_Error $e) {
mailchimp_error('order_submit.error', mailchimp_error_trace($e, "$call :: {$item->getId()}"));
return false;
} catch (Exception $e) {
mailchimp_error('order_submit.error', mailchimp_error_trace($e, "$call :: {$item->getId()}"));
return false;
}
}
mailchimp_debug('order_submit', 'no order found', $item);
return false;
}
/**
* After the resources have been loaded and pushed
*/
protected function complete()
{
mailchimp_log('order_submit.completed', 'Done with the order sync.');
// add a timestamp for the orders sync completion
$this->setResourceCompleteTime();
// this is the last thing we're doing so it's complete as of now.
$this->flagStopSync();
}
}

View File

@@ -0,0 +1,91 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/14/16
* Time: 10:57 AM
*/
class MailChimp_WooCommerce_Process_Products extends MailChimp_WooCommerce_Abstract_Sync
{
/**
* @var string
*/
protected $action = 'mailchimp_woocommerce_process_products';
public static function push()
{
$job = new MailChimp_WooCommerce_Process_Products();
$job->flagStartSync();
wp_queue($job);
}
/**
* @return string
*/
public function getResourceType()
{
return 'products';
}
/**
* @param MailChimp_WooCommerce_Product $item
*
* @return mixed
*/
protected function iterate($item) {
if ($item instanceof MailChimp_WooCommerce_Product) {
mailchimp_debug('product_sync', "#{$item->getId()}", $item->toArray());
// need to run the delete option on this before submitting because the API does not support PATCH yet.
$this->mailchimp()->deleteStoreProduct($this->store_id, $item->getId());
// add the product.
try {
// make the call
$response = $this->mailchimp()->addStoreProduct($this->store_id, $item, false);
mailchimp_log('product_sync.success', "addStoreProduct :: #{$response->getId()}");
return $response;
} catch (MailChimp_WooCommerce_ServerError $e) {
mailchimp_error('product_sync.error', mailchimp_error_trace($e, "addStoreProduct :: {$item->getId()}"));
} catch (MailChimp_WooCommerce_Error $e) {
mailchimp_error('product_sync.error', mailchimp_error_trace($e, "addStoreProduct :: {$item->getId()}"));
} catch (Exception $e) {
mailchimp_error('product_sync.error', mailchimp_error_trace($e, "addStoreProduct :: {$item->getId()}"));
}
}
return false;
}
/**
* Called after all the products have been iterated and processed into MailChimp
*/
protected function complete()
{
mailchimp_log('product_sync.completed', 'Done with the product sync :: queuing up the orders next!');
// add a timestamp for the product sync completion
$this->setResourceCompleteTime();
$prevent_order_sync = get_option('mailchimp-woocommerce-sync.orders.prevent', false);
// only do this if we're not strictly syncing products ( which is the default ).
if (!$prevent_order_sync) {
// since the products are all good, let's sync up the orders now.
wp_queue(new MailChimp_WooCommerce_Process_Orders());
}
// since we skipped the orders feed we can delete this option.
delete_option('mailchimp-woocommerce-sync.orders.prevent');
}
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 10/6/17
* Time: 11:14 AM
*/
class MailChimp_WooCommerce_SingleCoupon extends WP_Job
{
public $coupon_data;
public $post_id;
/**
* MailChimp_WooCommerce_Coupon_Sync constructor.
* @param $post_id
*/
public function __construct($post_id = null)
{
$this->post_id = $post_id;
}
/**
* @return null
*/
public function handle()
{
try {
if (!mailchimp_is_configured()) {
mailchimp_debug(get_called_class(), 'mailchimp is not configured properly');
return false;
}
if (empty($this->post_id)) {
mailchimp_error('promo_code.failure', "could not process coupon {$this->post_id}");
return;
}
$api = mailchimp_get_api();
$store_id = mailchimp_get_store_id();
$transformer = new MailChimp_WooCommerce_Transform_Coupons();
$code = $transformer->transform($this->post_id);
$api->addPromoRule($store_id, $code->getAttachedPromoRule(), true);
$api->addPromoCodeForRule($store_id, $code->getAttachedPromoRule(), $code, true);
mailchimp_log('promo_code.update', "updated promo code {$code->getCode()}");
} catch (\Exception $e) {
$promo_code = isset($code) ? "code {$code->getCode()}" : "id {$this->post_id}";
mailchimp_error('promo_code.error', mailchimp_error_trace($e, "error updating promo {$promo_code}"));
}
}
}

View File

@@ -0,0 +1,238 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/15/16
* Time: 11:42 AM
*/
class MailChimp_WooCommerce_Single_Order extends WP_Job
{
public $order_id;
public $cart_session_id;
public $campaign_id;
public $landing_site;
public $is_update = false;
public $is_admin_save = false;
public $partially_refunded = false;
protected $woo_order_number = false;
/**
* MailChimp_WooCommerce_Single_Order constructor.
* @param null $order_id
* @param null $cart_session_id
* @param null $campaign_id
* @param null $landing_site
*/
public function __construct($order_id = null, $cart_session_id = null, $campaign_id = null, $landing_site = null)
{
if (!empty($order_id)) $this->order_id = $order_id;
if (!empty($cart_session_id)) $this->cart_session_id = $cart_session_id;
if (!empty($campaign_id)) $this->campaign_id = $campaign_id;
if (!empty($landing_site)) $this->landing_site = $landing_site;
}
/**
* @return bool
*/
public function handle()
{
$this->process();
return false;
}
public function process()
{
if (!mailchimp_is_configured() || !($api = mailchimp_get_api())) {
mailchimp_debug(get_called_class(), 'mailchimp is not configured properly');
return false;
}
$store_id = mailchimp_get_store_id();
if (!($woo_order_number = $this->getRealOrderNumber())) {
mailchimp_log('order_submit.failure', "There is no real order number to use.");
return false;
}
// skip amazon orders
if ($this->isAmazonOrder()) {
mailchimp_log('validation.amazon', "Order #{$woo_order_number} was placed through Amazon. Skipping!");
return false;
}
$job = new MailChimp_WooCommerce_Transform_Orders();
// set the campaign ID
$job->campaign_id = $this->campaign_id;
$call = ($api_response = $api->getStoreOrder($store_id, $woo_order_number)) ? 'updateStoreOrder' : 'addStoreOrder';
if (!$this->is_admin_save && $call === 'addStoreOrder' && $this->is_update === true) {
return false;
}
// if we already pushed this order into the system, we need to unset it now just in case there
// was another campaign that had been sent and this was only an order update.
if ($call === 'updateStoreOrder') {
$job->campaign_id = null;
$this->campaign_id = null;
$this->landing_site = null;
}
// will either add or update the order
try {
if (!($order_post = get_post($this->order_id))) {
return false;
}
// transform the order
$order = $job->transform($order_post);
// will be the same as the customer id. an md5'd hash of a lowercased email.
$this->cart_session_id = $order->getCustomer()->getId();
// delete the AC cart record.
$deleted_abandoned_cart = !empty($this->cart_session_id) && $api->deleteCartByID($store_id, $this->cart_session_id);
// skip amazon orders
if ($order->isFlaggedAsAmazonOrder()) {
mailchimp_log('validation.amazon', "Order #{$woo_order_number} was placed through Amazon. Skipping!");
return false;
}
// if the order is in failed or cancelled status - and it's brand new, we shouldn't submit it.
if ($call === 'addStoreOrder' && in_array($order->getFinancialStatus(), array('failed', 'cancelled'))) {
return false;
}
mailchimp_debug('order_submit', "#{$woo_order_number}", $order->toArray());
// if we're overriding this we need to set it here.
if ($this->partially_refunded) {
$order->setFinancialStatus('partially_refunded');
}
$log = "$call :: #{$order->getId()} :: email: {$order->getCustomer()->getEmailAddress()}";
// only do this stuff on new orders
if ($call === 'addStoreOrder') {
// apply a campaign id if we have one.
if (!empty($this->campaign_id)) {
$log .= ' :: campaign id ' . $this->campaign_id;
$order->setCampaignId($this->campaign_id);
}
// apply the landing site if we have one.
if (!empty($this->landing_site)) {
$log .= ' :: landing site ' . $this->landing_site;
$order->setLandingSite($this->landing_site);
}
}
// update or create
$api_response = $api->$call($store_id, $order, false);
if (empty($api_response)) {
mailchimp_error('order_submit.failure', "$call :: #{$order->getId()} :: email: {$order->getCustomer()->getEmailAddress()} produced a blank response from MailChimp");
return $api_response;
}
if ($deleted_abandoned_cart) {
$log .= " :: abandoned cart deleted [{$this->cart_session_id}]";
}
mailchimp_log('order_submit.success', $log);
return $api_response;
} catch (\Exception $e) {
$message = strtolower($e->getMessage());
mailchimp_error('order_submit.tracing_error', $e);
if (!isset($order)) {
// transform the order
$order = $job->transform(get_post($this->order_id));
$this->cart_session_id = $order->getCustomer()->getId();
}
// this can happen when a customer changes their email.
if (isset($order) && strpos($message, 'not be changed')) {
try {
mailchimp_log('order_submit.deleting_customer', "#{$order->getId()} :: email: {$order->getCustomer()->getEmailAddress()}");
// delete the customer before adding it again.
$api->deleteCustomer($store_id, $order->getCustomer()->getId());
// update or create
$api_response = $api->$call($store_id, $order, false);
$log = "Deleted Customer :: $call :: #{$order->getId()} :: email: {$order->getCustomer()->getEmailAddress()}";
if (!empty($job->campaign_id)) {
$log .= ' :: campaign id '.$job->campaign_id;
}
mailchimp_log('order_submit.success', $log);
// if we're adding a new order and the session id is here, we need to delete the AC cart record.
if (!empty($this->cart_session_id)) {
$api->deleteCartByID($store_id, $this->cart_session_id);
}
return $api_response;
} catch (\Exception $e) {
mailchimp_error('order_submit.error', mailchimp_error_trace($e, 'deleting-customer-re-add :: #'.$this->order_id));
}
}
}
return false;
}
/**
* @return bool
*/
public function getRealOrderNumber()
{
try {
if (empty($this->order_id) || !($order_post = get_post($this->order_id))) {
return false;
}
$woo = new WC_Order($order_post);
return $this->woo_order_number = $woo->get_order_number();
} catch (\Exception $e) {
$this->woo_order_number = false;
mailchimp_error('order_sync.failure', mailchimp_error_trace($e, "{$this->order_id} could not be loaded"));
return false;
}
}
/**
* @return bool
*/
public function isAmazonOrder()
{
try {
if (empty($this->order_id) || !($order_post = get_post($this->order_id))) {
return false;
}
$woo = new WC_Order($order_post);
// just skip these altogether because we can't submit any amazon orders anyway.
return mailchimp_string_contains($woo->get_billing_email(), '@marketplace.amazon.com');
} catch (\Exception $e) {
return false;
}
}
}

View File

@@ -0,0 +1,117 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/15/16
* Time: 11:42 AM
*/
class MailChimp_WooCommerce_Single_Product extends WP_Job
{
public $product_id;
protected $store_id;
protected $api;
protected $service;
/**
* MailChimp_WooCommerce_Single_Order constructor.
* @param null|int $product_id
*/
public function __construct($product_id = null)
{
if (!empty($product_id)) {
$this->product_id = $product_id instanceof WP_Post ? $product_id->ID : $product_id;
}
}
/**
* @return bool
*/
public function handle()
{
$this->process();
return false;
}
/**
* @return bool|MailChimp_WooCommerce_Product
*/
public function process()
{
if (empty($this->product_id)) {
return false;
}
if (!mailchimp_is_configured()) {
mailchimp_debug(get_called_class(), 'mailchimp is not configured properly');
return false;
}
if ($this->api()->getStoreProduct($this->store_id, $this->product_id)) {
$this->api()->deleteStoreProduct($this->store_id, $this->product_id);
}
try {
if (!($product_post = get_post($this->product_id))) {
return false;
}
$product = $this->transformer()->transform($product_post);
mailchimp_debug('product_submit.debug', "#{$this->product_id}", $product->toArray());
$this->api()->addStoreProduct($this->store_id, $product, false);
mailchimp_log('product_submit.success', "addStoreProduct :: #{$product->getId()}");
update_option('mailchimp-woocommerce-last_product_updated', $product->getId());
return $product;
} catch (MailChimp_WooCommerce_ServerError $e) {
mailchimp_error('product_submit.error', mailchimp_error_trace($e, "addStoreProduct :: #{$this->product_id}"));
} catch (MailChimp_WooCommerce_Error $e) {
mailchimp_log('product_submit.error', mailchimp_error_trace($e, "addStoreProduct :: #{$this->product_id}"));
} catch (Exception $e) {
mailchimp_log('product_submit.error', mailchimp_error_trace($e, "addStoreProduct :: #{$this->product_id}"));
}
return false;
}
/**
* @return MailChimp_WooCommerce_MailChimpApi
*/
public function api()
{
if (is_null($this->api)) {
$this->store_id = mailchimp_get_store_id();
$options = get_option('mailchimp-woocommerce', array());
if (!empty($this->store_id) && is_array($options) && isset($options['mailchimp_api_key'])) {
return $this->api = new MailChimp_WooCommerce_MailChimpApi($options['mailchimp_api_key']);
}
throw new \RuntimeException('The MailChimp API is not currently configured!');
}
return $this->api;
}
/**
* @return MailChimp_WooCommerce_Transform_Products
*/
public function transformer()
{
if (is_null($this->service)) {
return $this->service = new MailChimp_WooCommerce_Transform_Products();
}
return $this->service;
}
}

View File

@@ -0,0 +1,154 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 11/14/16
* Time: 9:38 AM
*/
class MailChimp_WooCommerce_User_Submit extends WP_Job
{
public $user_id;
public $subscribed;
public $updated_data;
/**
* MailChimp_WooCommerce_User_Submit constructor.
* @param null $user_id
* @param null $subscribed
* @param WP_User|null $updated_data
*/
public function __construct($user_id = null, $subscribed = null, $updated_data = null)
{
if (!empty($user_id)) {
$this->user_id = $user_id;
}
if (is_bool($subscribed)) {
$this->subscribed = $subscribed;
}
if (!empty($updated_data)) {
$this->updated_data = $updated_data->to_array();
}
}
/**
* @return bool
*/
public function handle()
{
if (!mailchimp_is_configured()) {
mailchimp_debug(get_called_class(), 'mailchimp is not configured properly');
return false;
}
$options = get_option('mailchimp-woocommerce', array());
$store_id = mailchimp_get_store_id();
// load up the user.
$user = new WP_User($this->user_id);
// we need a valid user, a valid store id and options to continue
if ($user->ID <= 0 || empty($store_id) || !is_array($options)) {
// seems as if the database records are not being set by the time this queue job is fired,
// just a precautionary to make sure it's available during
sleep(3);
$options = get_option('mailchimp-woocommerce', array());
$store_id = mailchimp_get_store_id();
// load up the user.
$user = new WP_User($this->user_id);
if ($user->ID <= 0 || empty($store_id) || !is_array($options)) {
mailchimp_log('member.sync', "Invalid Data For Submission :: {$user->user_email}");
return false;
}
}
// if we have a null value, we need to grab the correct user meta for is_subscribed
if (is_null($this->subscribed)) {
$user_subscribed = get_user_meta($this->user_id, 'mailchimp_woocommerce_is_subscribed', true);
if ($user_subscribed === '' || $user_subscribed === null) {
mailchimp_log('member.sync', "Skipping sync for {$user->user_email} because no subscriber status has been set");
return false;
}
$this->subscribed = (bool) $user_subscribed;
}
$api_key = isset($options['mailchimp_api_key']) ? $options['mailchimp_api_key'] : false;
$list_id = isset($options['mailchimp_list']) ? $options['mailchimp_list'] : false;
// we need a valid api key and list id to continue
if (empty($api_key) || empty($list_id)) {
mailchimp_log('member.sync', "Invalid Api Key or ListID :: {$user->user_email}");
return false;
}
// don't let anyone be unsubscribed from the list - that should only happen on email campaigns
// and someone clicking the unsubscribe linkage.
if (!$this->subscribed) {
return false;
}
$api = new MailChimp_WooCommerce_MailChimpApi($api_key);
$merge_vars = array();
$fn = trim($user->first_name);
$ln = trim($user->last_name);
if (!empty($fn)) $merge_vars['FNAME'] = $fn;
if (!empty($ln)) $merge_vars['LNAME'] = $ln;
try {
// see if we have a member.
$api->member($list_id, $user->user_email);
// if we're updating a member and the email is different, we need to delete the old person
if (is_array($this->updated_data) && isset($this->updated_data['user_email'])) {
if ($this->updated_data['user_email'] !== $user->user_email) {
// delete the old
$api->deleteMember($list_id, $this->updated_data['user_email']);
// subscribe the new
$api->subscribe($list_id, $user->user_email, $this->subscribed, $merge_vars);
mailchimp_log('member.sync', 'Subscriber Swap '.$this->updated_data['user_email'].' to '.$user->user_email, $merge_vars);
return false;
}
}
// ok let's update this member
$api->update($list_id, $user->user_email, $this->subscribed, $merge_vars);
mailchimp_log('member.sync', "Updated Member {$user->user_email}", $merge_vars);
} catch (\Exception $e) {
// if we have a 404 not found, we can create the member
if ($e->getCode() == 404) {
try {
$api->subscribe($list_id, $user->user_email, $this->subscribed, $merge_vars);
mailchimp_log('member.sync', "Subscribed Member {$user->user_email}", $merge_vars);
} catch (\Exception $e) {
mailchimp_log('member.sync', $e->getMessage());
}
return false;
}
mailchimp_error('member.sync', mailchimp_error_trace($e, $user->user_email));
}
return false;
}
}

View File

@@ -0,0 +1,103 @@
<?php
/*
Plugin Name: WP Background Processing
Plugin URI: https://github.com/A5hleyRich/wp-background-processing
Description: Asynchronous requests and background processing in WordPress.
Author: Delicious Brains Inc.
Version: 1.0
Author URI: https://deliciousbrains.com/
*/
$queue_folder_path = plugin_dir_path( __FILE__ );
require_once $queue_folder_path . 'queue/classes/wp-job.php';
require_once $queue_folder_path . 'queue/classes/wp-queue.php';
require_once $queue_folder_path . 'queue/classes/worker/wp-worker.php';
require_once $queue_folder_path . 'queue/classes/worker/wp-http-worker.php';
global $wp_queue;
$wp_queue = new WP_Queue();
// Add WP CLI commands
if (defined( 'WP_CLI' ) && WP_CLI) {
try {
/**
* Service push to MailChimp
*
* <type>
* : product_sync order_sync order product
*/
function mailchimp_cli_push_command( $args, $assoc_args ) {
if (is_array($args) && isset($args[0])) {
switch($args[0]) {
case 'product_sync':
wp_queue(new MailChimp_WooCommerce_Process_Products());
WP_CLI::success("queued up the product sync!");
break;
case 'order_sync':
wp_queue(new MailChimp_WooCommerce_Process_Orders());
WP_CLI::success("queued up the order sync!");
break;
case 'order':
if (!isset($args[1])) {
wp_die('You must specify an order id as the 2nd parameter.');
}
wp_queue(new MailChimp_WooCommerce_Single_Order($args[1]));
WP_CLI::success("queued up the order {$args[1]}!");
break;
case 'product':
if (!isset($args[1])) {
wp_die('You must specify a product id as the 2nd parameter.');
}
wp_queue(new MailChimp_WooCommerce_Single_Product($args[1]));
WP_CLI::success("queued up the product {$args[1]}!");
break;
}
}
};
WP_CLI::add_command( 'mailchimp_push', 'mailchimp_cli_push_command');
require_once $queue_folder_path . 'queue/classes/cli/queue-command.php';
WP_CLI::add_command( 'queue', 'Queue_Command' );
} catch (\Exception $e) {}
}
if (!mailchimp_running_in_console() && mailchimp_is_configured()) {
// fire up the http worker container
new WP_Http_Worker($wp_queue);
}
// if we're not running in the console, and the http_worker is not running
if (mailchimp_should_init_queue()) {
try {
// if we do not have a site transient for the queue listener
if (!get_site_transient('http_worker_queue_listen')) {
// set the site transient to expire in 50 seconds so this will not happen too many times
// but still work for cron scripts on the minute mark.
set_site_transient( 'http_worker_queue_listen', microtime(), 50);
// if we have available jobs, call the http worker manually
if ($wp_queue->available_jobs()) {
mailchimp_call_http_worker_manually();
}
}
} catch (\Exception $e) {}
}
if (!function_exists( 'wp_queue')) {
/**
* WP queue.
*
* @param WP_Job $job
* @param int $delay
*/
function wp_queue( WP_Job $job, $delay = 0 ) {
global $wp_queue;
$wp_queue->push( $job, $delay );
do_action( 'wp_queue_job_pushed', $job );
}
}

View File

@@ -0,0 +1,391 @@
<?php
/**
* Manage queue and jobs.
*
* @package wp-cli
*/
class Queue_Command extends WP_CLI_Command {
/**
* Timestamp of when this worker started processing the queue.
*
* @var int
*/
protected $start_time;
protected $pid;
protected $command_called;
/**
* Queue_Command constructor.
*/
public function __construct()
{
$this->pid = getmypid();
register_shutdown_function(array($this, 'on_shutdown'));
}
/**
* make sure we remove the site transient
*/
public function on_shutdown()
{
switch ($this->command_called) {
case 'listen':
$this->deleteQueueTimer();
break;
}
}
/**
* Get the expiration for the single cron job
*
* @throws \WP_CLI\ExitException
*/
public function expired_at()
{
$time = $this->getQueueTimer();
if (empty($time)) {
WP_CLI::error('no timer running');
wp_die();
}
WP_CLI::success("Next iteration will happen no later than ".(string) mailchimp_date_utc($time));
wp_die();
}
/**
* Flush all of the records in the queue.
*/
public function flush()
{
global $wpdb;
$this->command_called = 'flush';
$wpdb->query("DELETE FROM {$wpdb->prefix}queue");
}
/**
* Show all the records in the queue.
*/
public function show()
{
global $wpdb;
$this->command_called = 'show';
print_r($wpdb->get_results("SELECT * FROM {$wpdb->prefix}queue"));
}
/**
* Creates the queue tables.
*
* @subcommand create-tables
*/
public function create_tables( $args, $assoc_args = array() ) {
$this->command_called = 'create_tables';
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
global $wpdb;
$wpdb->hide_errors();
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE {$wpdb->prefix}queue (
id bigint(20) NOT NULL AUTO_INCREMENT,
job text NOT NULL,
attempts tinyint(1) NOT NULL DEFAULT 0,
locked tinyint(1) NOT NULL DEFAULT 0,
locked_at datetime DEFAULT NULL,
available_at datetime NOT NULL,
created_at datetime NOT NULL,
PRIMARY KEY (id)
) $charset_collate;";
dbDelta( $sql );
$sql = "CREATE TABLE {$wpdb->prefix}failed_jobs (
id bigint(20) NOT NULL AUTO_INCREMENT,
job text NOT NULL,
failed_at datetime NOT NULL,
PRIMARY KEY (id)
) $charset_collate;";
dbDelta( $sql );
WP_CLI::success( "Table {$wpdb->prefix}queue created." );
}
/**
* Run the queue listener to process jobs
*
* ## OPTIONS
*
* [--force=<0>]
* : Force the listener to ignore the transient and run
*
* [--daemon=<0>]
* : Running the command as a true process using a manager to keep alive.
* If using WP CRON use --daemon=0
* If using a process manager, do nothing or pass in 1
*
* [--multiple=<0>]
* : Allow multiple processes to run at the same time. ( default is 0 )
*
* [--sleep_processing=<1>]
* : How long to sleep between jobs. ( default is 1 second )
*
* [--sleep_empty=<5>]
* : How long to sleep between jobs when nothing is in the queue. ( default is 5 seconds )
* ---
*
* ## EXAMPLES
*
* wp queue listen --daemon=1
* wp queue listen --daemon=0 --sleep_empty=10
*
* ---
*
* @subcommand listen
* @param $args
* @param array $assoc_args
*/
public function listen( $args, $assoc_args = array() ) {
global $wp_queue;
$this->command_called = 'listen';
$this->start_time = time(); // Set start time of current command
$allow_multiple = (isset($assoc_args['multiple']) ? (bool) $assoc_args['multiple'] : null) === true;
$running_as_daemon = (isset($assoc_args['daemon']) ? (bool) $assoc_args['daemon'] : null) === true;
$force = (isset($assoc_args['force']) ? (bool) $assoc_args['force'] : null) === true;
$sleep_between_jobs = isset($assoc_args['sleep_processing']) ? (int) $assoc_args['sleep_processing'] : 1;
$sleep_when_empty = isset($assoc_args['sleep_empty']) ? (int) $assoc_args['sleep_empty'] : 5;
$expire_time = $this->getQueueTimer();
if (!$force && !$allow_multiple) {
if (!empty($expire_time) && ($expire_time+100) > $this->start_time) {
WP_CLI::log('Currently running in another process');
//mailchimp_debug("queue", $message = "wp queue listen is running in another process or waiting to restart at [{$expire_time}] but clock says [{$this->start_time}].");
wp_die();
}
}
$this->updateQueueTimer();
mailchimp_debug("queue", $message = "[start] queue listen process_id [{$this->pid}] :: max_time [{$this->getServerMaxExecutionTime()}] :: memory limit [{$this->getServerMemoryLimit()}]");
WP_CLI::log($message);
$worker = new WP_Worker( $wp_queue );
$loop_counter = 0;
// if the user specifies that they want to run as a daemon we need to allow that.
while ($running_as_daemon || $this->all_good_under_the_hood()) {
$loop_counter++;
// if we're doing single processing only, set the transient
if (!$allow_multiple) {
if ($loop_counter % 5 === 0) {
$this->updateQueueTimer(time() + 300);
}
}
// allow queue to break out of the forever loop if something is going wrong by adding a transient
if ((bool) get_site_transient('kill_wp_queue_listener')) {
break;
}
// log it in increments of 20 to be lighter on the log file
if ($loop_counter % 20 === 0) {
mailchimp_debug("queue listen", $message = "process id {$this->pid} :: loop #{$loop_counter}");
WP_CLI::log($message);
}
$sleep = $sleep_when_empty;
// if the worker has a job, apply the sleep between job timeout
if ($worker->should_run() && $worker->process_next_job()) {
$sleep = $sleep_between_jobs;
if (($job_name = $worker->get_job_name()) !== 'WP_Worker') {
WP_CLI::success('Processed: ' . $job_name);
}
}
sleep($sleep);
}
if (!$allow_multiple) {
$this->deleteQueueTimer();
}
mailchimp_debug("queue", $message = '[end] queue listen process_id = '.$this->pid);
WP_CLI::log($message);
exit;
}
/**
* Process the next job in the queue.
* @subcommand work
*/
public function work( $args, $assoc_args = array() ) {
global $wp_queue;
$this->command_called = 'work';
$worker = new WP_Worker( $wp_queue );
if ( $worker->should_run() ) {
if ( $worker->process_next_job() ) {
WP_CLI::success( 'Processed: ' . $worker->get_job_name() );
} else {
WP_CLI::warning( 'Failed: ' . $worker->get_job_name() );
}
} else {
WP_CLI::log( 'No jobs to process...' );
}
}
/**
* Show queue status.
*/
public function status( $args, $assoc_args = array() ) {
global $wp_queue;
$this->command_called = 'status';
WP_CLI::log( $wp_queue->available_jobs() . ' jobs in the queue' );
WP_CLI::log( $wp_queue->failed_jobs() . ' failed jobs' );
}
/**
* Push failed jobs back onto the queue.
*
* @subcommand restart-failed
*/
public function restart_failed( $args, $assoc_args = array() ) {
global $wp_queue;
$this->command_called = 'restart_failed';
if ( ! $wp_queue->failed_jobs() ) {
WP_CLI::log( 'No failed jobs to restart...' );
return;
}
$count = $wp_queue->restart_failed_jobs();
WP_CLI::success( $count . ' failed jobs pushed to the queue' );
}
/**
* @return mixed
*/
protected function deleteQueueTimer()
{
global $wpdb;
$key = 'mailchimp_woocommerce_queue_listen';
$sql = $wpdb->prepare("DELETE FROM {$wpdb->options} WHERE option_name = %s", $key);
return $wpdb->query($sql);
}
/**
* @return null
*/
protected function getQueueTimer()
{
global $wpdb;
$key = 'mailchimp_woocommerce_queue_listen';
$row = $wpdb->get_row($wpdb->prepare("SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $key));
return is_object($row) ? (int) unserialize($row->option_value) : null;
}
/**
* @param null $time
* @return mixed
*/
protected function updateQueueTimer($time = null)
{
global $wpdb;
if (empty($this->start_time)) {
$this->start_time = time();
}
$value = $time ?: $this->start_time+600;
$values = array(
'option_value' => serialize($value),
'autoload' => 'no',
);
$key = 'mailchimp_woocommerce_queue_listen';
$updated = $wpdb->update($wpdb->options, $values, array('option_name' => $key));
if ($updated) {
return $updated;
}
$values['option_name'] = $key;
return $wpdb->insert($wpdb->options, $values);
}
/**
* @return bool
*/
protected function all_good_under_the_hood()
{
return !$this->time_exceeded() && !$this->memory_exceeded();
}
/**
* Memory exceeded
*
* Ensures the worker process never exceeds 80%
* of the maximum allowed PHP memory.
*
* @return bool
*/
protected function memory_exceeded() {
return memory_get_usage( true ) >= ($this->get_memory_limit() * 0.8);
}
/**
* Get memory limit
*
* @return int
*/
protected function get_memory_limit() {
return intval($this->getServerMemoryLimit()) * 1024 * 1024;
}
/**
* Time exceeded
*
* Ensures the worker never exceeds a sensible time limit (50s by default).
* A timeout limit of 30s is common on shared hosting.
*
* @return bool
*/
protected function time_exceeded() {
return time() >= $this->start_time + apply_filters( 'cli_worker_default_time_limit', ($this->getServerMaxExecutionTime() - 10));
}
/**
* @return int
*/
protected function getServerMaxExecutionTime()
{
$time_limit = (int) function_exists( 'ini_get' ) ? ini_get( 'max_execution_time' ) : 30;
if (!$time_limit || -1 == $time_limit) {
$time_limit = 1800;
}
return $time_limit;
}
/**
* @return string
*/
protected function getServerMemoryLimit()
{
$memory_limit = function_exists( 'ini_get' ) ? ini_get( 'memory_limit' ) : '128M';
if (!$memory_limit || -1 == $memory_limit) {
$memory_limit = '32000M';
}
return (int) preg_replace_callback('/(\-?\d+)(.?)/', function ($m) {
return $m[1] * pow(1024, strpos('BKMG', $m[2]));
}, strtoupper($memory_limit));
}
}

View File

@@ -0,0 +1,340 @@
<?php
if ( ! class_exists( 'WP_Http_Worker' ) ) {
class WP_Http_Worker extends WP_Worker {
/**
* Has the worker been dispatched in this request?
*
* @var bool
*/
protected $dispatched = false;
/**
* Timestamp of when this worker started processing the queue.
*
* @var int
*/
protected $start_time;
/**
* WP_Http_Worker constructor
*
* @param WP_Queue $queue
*/
public function __construct( $queue ) {
parent::__construct( $queue );
// Cron health check
add_action( 'http_worker_cron', array( $this, 'handle_cron' ) );
add_filter( 'cron_schedules', array( $this, 'schedule_cron' ) );
$this->maybe_schedule_cron();
// Dispatch handlers
add_action( 'wp_ajax_http_worker', array( $this, 'maybe_handle' ) );
add_action( 'wp_ajax_nopriv_http_worker', array( $this, 'maybe_handle' ) );
// Dispatch listener
add_action( 'wp_queue_job_pushed', array( $this, 'maybe_dispatch_worker' ) );
if (isset($_REQUEST['action']) && $_REQUEST['action'] === 'http_worker' && check_ajax_referer( 'http_worker', 'nonce', false)) {
add_action('init', array($this, 'handle'));
}
}
/**
* Maybe handle
*
* Process the queue if no other HTTP worker is running and
* the current worker is within server memory and time limit constraints.
* Automatically dispatch another worker and kill the current process if
* jobs remain in the queue and server limits reached.
*/
public function maybe_handle() {
check_ajax_referer( 'http_worker', 'nonce' );
$this->handle();
}
/**
*
*/
public function handle()
{
if ( $this->is_worker_running() ) {
// Worker already running, die
wp_die();
}
// Lock worker to prevent multiple instances spawning
$this->lock_worker();
$processed_something = false;
// Loop over jobs while within server limits
while ( ! $this->time_exceeded() && ! $this->memory_exceeded() ) {
if ( $this->should_run() ) {
$this->process_next_job();
$processed_something = true;
} else {
break;
}
}
// Unlock worker to allow another instance to be spawned
$this->unlock_worker();
$available_jobs = $this->queue->available_jobs();
if (!$processed_something && $available_jobs) {
mailchimp_debug('queue_tracer', "HTTPWorker@handle", array(
'jobs' => $available_jobs,
'time_exceeded' => $this->time_exceeded(),
'memory_exceeded' => $this->memory_exceeded(),
'memory_limit' => $this->get_memory_limit(),
'memory_usage' => memory_get_usage(true),
'ini_memory' => ini_get('memory_limit'),
'php_version' => phpversion(),
));
wp_die();
}
if ($available_jobs) {
// Job queue not empty, dispatch async worker request
$this->dispatch();
}
wp_die();
}
/**
* Memory exceeded
*
* Ensures the worker process never exceeds 80%
* of the maximum allowed PHP memory.
*
* @return bool
*/
protected function memory_exceeded() {
$memory_limit = $this->get_memory_limit() * 0.8; // 80% of max memory
$current_memory = memory_get_usage( true );
$return = false;
if ( $current_memory >= $memory_limit ) {
$return = true;
}
return apply_filters( 'http_worker_memory_exceeded', $return );
}
/**
* Get memory limit
*
* @return int
*/
protected function get_memory_limit() {
if ( function_exists( 'ini_get' ) ) {
$memory_limit = ini_get( 'memory_limit' );
} else {
// Sensible default
$memory_limit = '128M';
}
if ( ! $memory_limit || -1 == $memory_limit ) {
// Unlimited, set to 32GB
$memory_limit = '32000M';
}
return (int) preg_replace_callback('/(\-?\d+)(.?)/', function ($m) {
return $m[1] * pow(1024, strpos('BKMG', $m[2]));
}, strtoupper($memory_limit));
}
/**
* Time exceeded
*
* Ensures the worker never exceeds a sensible time limit (20s by default).
* A timeout limit of 30s is common on shared hosting.
*
* @return bool
*/
protected function time_exceeded() {
$finish = $this->start_time + apply_filters( 'http_worker_default_time_limit', 20 ); // 20 seconds
$return = false;
if ( time() >= $finish ) {
$return = true;
}
return apply_filters( 'http_worker_time_exceeded', $return );
}
/**
* Maybe dispatch worker
*
* Dispatch a worker process if we haven't already in this request
* and no other HTTP workers are running.
*
* @param WP_Job $job
*/
public function maybe_dispatch_worker( $job ) {
if ( $this->is_worker_running() ) {
// HTTP worker already running, return
return;
}
// Dispatch async worker request
$this->dispatch();
}
/**
* Is worker running
*
* Check if another instance of the HTTP worker is running.
*
* @return bool
*/
protected function is_worker_running() {
if ( get_site_transient( 'http_worker_lock' ) ) {
// Process already running
return true;
}
return false;
}
/**
* Lock worker
*
* Lock the HTTP worker to prevent multiple instances running.
*/
protected function lock_worker() {
$this->start_time = time(); // Set start time of current worker
$lock_duration = apply_filters( 'http_worker_lock_time', 60 ); // 60 seconds
set_site_transient( 'http_worker_lock', microtime(), $lock_duration );
}
/**
* Unlock worker
*
* Unlock the HTTP worker to allow other instances to be spawned.
*/
protected function unlock_worker() {
delete_site_transient( 'http_worker_lock' );
}
/**
* Dispatch
*
* Fire off a non-blocking async request if we haven't already
* in this request.
*/
protected function dispatch() {
if ( $this->is_http_worker_disabled() ) {
return;
}
if ( ! $this->dispatched ) {
$this->async_request();
}
$this->dispatched = true;
}
/**
* Is HTTP worker disabled
*
* @return bool
*/
protected function is_http_worker_disabled() {
if ( ! defined( 'DISABLE_WP_HTTP_WORKER' ) || true !== DISABLE_WP_HTTP_WORKER ) {
return false;
}
return true;
}
/**
* Async request
*
* Fire off a non-blocking request to admin-ajax.php.
*
* @return array|WP_Error
*/
protected function async_request() {
$action = 'http_worker';
$query_args = apply_filters( 'http_worker_query_args', array(
'action' => $action,
'nonce' => wp_create_nonce( $action ),
) );
$query_url = apply_filters( 'http_worker_query_url', admin_url( 'admin-ajax.php' ) );
$post_args = apply_filters( 'http_worker_post_args', array(
'timeout' => 0.01,
'blocking' => false,
'cookies' => $_COOKIE,
'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
) );
$url = add_query_arg( $query_args, $query_url );
return wp_remote_post( esc_url_raw( $url ), $post_args );
}
/**
* @return bool
*/
public function handle_cron() {
if ($this->is_worker_running()) {
wp_die();
}
if ($this->queue->available_jobs()) {
$this->dispatch();
return true;
}
return false;
}
/**
* Cron schedules
*
* @param $schedules
*
* @return mixed
*/
public function schedule_cron( $schedules ) {
$interval = apply_filters( 'http_worker_cron_interval', 3 );
// Adds every 3 minutes to the existing schedules.
$schedules[ 'http_worker_cron_interval' ] = array(
'interval' => MINUTE_IN_SECONDS * $interval,
'display' => sprintf( __( 'Every %d Minutes' ), $interval ),
);
return $schedules;
}
/**
* Maybe schedule cron
*
* Schedule health check cron if not disabled. Remove schedule if
* disabled and already scheduled.
*/
public function maybe_schedule_cron() {
if ( !$this->is_http_worker_disabled() && ! wp_next_scheduled( 'http_worker_cron' )) {
// Schedule health check
wp_schedule_event( time(), 'http_worker_cron_interval', 'http_worker_cron' );
}
}
}
}

View File

@@ -0,0 +1,96 @@
<?php
if ( ! class_exists( 'WP_Worker' ) ) {
class WP_Worker {
/**
* @var WP_Queue
*/
protected $queue;
/**
* @var WP_Job
*/
protected $payload;
/**
* WP_Worker constructor.
*
* @param WP_Queue $queue
*/
public function __construct( $queue ) {
$this->queue = $queue;
}
/**
* Should run
*
* @return bool
*/
public function should_run() {
if ( $this->queue->available_jobs() ) {
return true;
}
return false;
}
/**
* Process next job.
*
* @return bool
*/
public function process_next_job() {
$job = $this->queue->get_next_job();
if (empty($job)) {
return false;
}
$this->payload = unserialize( $job->job );
$this->queue->lock_job( $job );
$this->payload->set_job( $job );
try {
$this->payload->handle();
if ( $this->payload->is_deleted() ) {
// Job manually deleted, delete from queue
$this->queue->delete( $job );
return true;
}
if ( $this->payload->is_released() ) {
// Job manually released, release back onto queue
$this->queue->release( $job, $this->payload->get_delay() );
}
if ( ! $this->payload->is_deleted_or_released() ) {
// Job completed, delete from queue
$this->queue->delete( $job );
}
} catch ( Exception $e ) {
mailchimp_log('queue.error', "{$e->getMessage()} on {$e->getLine()} in {$e->getFile()}", array('job' => get_class($this->payload)));
$this->queue->release( $job );
return false;
}
if (defined('WP_CLI') && WP_CLI && property_exists($this->payload, 'should_kill_queue_listener') && $this->payload->should_kill_queue_listener === true) {
wp_die('killing queue listener');
}
return true;
}
/**
* Get job name.
*
* @return object
*/
public function get_job_name() {
return get_class( $this->payload );
}
}
}

View File

@@ -0,0 +1,105 @@
<?php
if ( ! class_exists( 'WP_Job' ) ) {
abstract class WP_Job {
public $should_kill_queue_listener = false;
/**
* @var stdClass
*/
private $job;
/**
* @var int
*/
private $delay = 0;
/**
* @var bool
*/
private $deleted = false;
/**
* @var bool
*/
private $released = false;
/**
* Set job
*
* @param $job
*/
public function set_job( $job ) {
$this->job = $job;
}
/**
* Delete the job from the queue
*/
protected function delete() {
$this->deleted = true;
}
/**
* Release a job back onto the queue
*
* @param int $delay
*/
protected function release( $delay = 0 ) {
$this->released = true;
$this->delay = $delay;
}
/**
* Attempts
*
* @return int
*/
protected function attempts() {
return (int) $this->job->attempts;
}
/**
* Is deleted.
*
* @return bool
*/
public function is_deleted() {
return $this->deleted;
}
/**
* Is released.
*
* @return bool
*/
public function is_released() {
return $this->released;
}
/**
* Is deleted for released
*
* @return bool
*/
public function is_deleted_or_released() {
return $this->is_deleted() || $this->is_released();
}
/**
* Get delay.
*
* @return int
*/
public function get_delay() {
return $this->delay;
}
/**
* Handle the job.
*/
abstract public function handle();
}
}

View File

@@ -0,0 +1,226 @@
<?php
if ( ! class_exists( 'WP_Queue' ) ) {
class WP_Queue {
/**
* @var string
*/
public $table;
/**
* @var string
*/
public $failed_table;
/**
* @var int
*/
public $release_time = 60;
/**
* WP_Queue constructor
*/
public function __construct() {
global $wpdb;
$this->table = $wpdb->prefix . 'queue';
$this->failed_table = $wpdb->prefix . 'failed_jobs';
}
/**
* Push a job onto the queue.
*
* @param WP_Job $job
* @param int $delay
*
* @return $this
*/
public function push( WP_Job $job, $delay = 0 ) {
global $wpdb;
$data = array(
'job' => maybe_serialize( $job ),
'available_at' => $this->datetime( $delay ),
'created_at' => $this->datetime(),
);
$id = $wpdb->insert( $this->table, $data );
return $this;
}
/**
* Release.
*
* @param object $job
* @param int $delay
*/
public function release( $job, $delay = 0 ) {
if ( $job->attempts >= 3 ) {
$this->failed( $job );
return;
}
global $wpdb;
$data = array(
'attempts' => $job->attempts + 1,
'locked' => 0,
'locked_at' => null,
'available_at' => $this->datetime( $delay ),
);
$where = array(
'id' => $job->id,
);
$wpdb->update( $this->table, $data, $where );
}
/**
* Failed
*
* @param stdClass $job
*/
protected function failed( $job ) {
global $wpdb;
$wpdb->insert( $this->failed_table, array(
'job' => $job->job,
'failed_at' => $this->datetime(),
) );
$payload = unserialize($job->job);
if (method_exists($payload, 'failed')) {
$payload->failed();
}
$this->delete( $job );
}
/**
* Delete.
*
* @param object $job
*/
public function delete( $job ) {
global $wpdb;
$wpdb->delete($this->table, array('id' => $job->id));
}
/**
* Get MySQL datetime.
*
* @param int $offset Seconds, can pass negative int.
*
* @return string
*/
protected function datetime($offset = 0) {
$timestamp = time() + $offset;
return gmdate( 'Y-m-d H:i:s', $timestamp );
}
/**
* Available jobs.
*/
public function available_jobs() {
global $wpdb;
$now = $this->datetime();
$sql = $wpdb->prepare( "
SELECT COUNT(*) FROM {$this->table}
WHERE available_at <= %s"
, $now );
return $wpdb->get_var( $sql );
}
/**
* Available jobs.
*/
public function failed_jobs() {
global $wpdb;
return $wpdb->get_var( "SELECT COUNT(*) FROM {$this->failed_table}" );
}
/**
* Restart failed jobs.
*/
public function restart_failed_jobs() {
global $wpdb;
$count = 0;
$jobs = $wpdb->get_results( "SELECT * FROM {$this->failed_table}" );
foreach ( $jobs as $job ) {
$this->push( maybe_unserialize( $job->job ) );
$wpdb->delete( $this->failed_table, array(
'id' => $job->id,
) );
$count++;
}
return $count;
}
/**
* Get next job.
*/
public function get_next_job() {
global $wpdb;
$this->maybe_release_locked_jobs();
$now = $this->datetime();
$sql = $wpdb->prepare( "
SELECT * FROM {$this->table}
WHERE locked = 0
AND available_at <= %s"
, $now );
return $wpdb->get_row( $sql );
}
/**
* Maybe release locked jobs.
*/
protected function maybe_release_locked_jobs() {
global $wpdb;
$expired = $this->datetime( - $this->release_time );
$sql = $wpdb->prepare( "
UPDATE {$this->table}
SET attempts = attempts + 1, locked = 0, locked_at = NULL
WHERE locked = 1
AND locked_at <= %s"
, $expired );
$wpdb->query( $sql );
}
/**
* Lock job.
*
* @param object $job
*/
public function lock_job( $job ) {
global $wpdb;
$data = array(
'locked' => 1,
'locked_at' => $this->datetime(),
);
$where = array(
'id' => $job->id,
);
$wpdb->update( $this->table, $data, $where );
}
}
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden

View File

@@ -0,0 +1,45 @@
<?php
/**
* The plugin bootstrap file
*
* This file is read by WordPress to generate the plugin information in the plugin
* admin area. This file also includes all of the dependencies used by the plugin,
* registers the activation and deactivation functions, and defines a function
* that starts the plugin.
*
* @link https://mailchimp.com
* @since 1.0.0
* @package MailChimp_WooCommerce
*
* @wordpress-plugin
* Plugin Name: MailChimp for WooCommerce
* Plugin URI: https://mailchimp.com/connect-your-store/
* Description: MailChimp - WooCommerce plugin
* Version: 2.1.7
* Author: MailChimp
* Author URI: https://mailchimp.com
* License: GPL-2.0+
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
* Text Domain: mailchimp-woocommerce
* Domain Path: /languages
* Requires at least: 4.4
* Tested up to: 4.9.2
*/
// If this file is called directly, abort.
if (!defined( 'WPINC')) {
die;
}
if (!isset($mailchimp_woocommerce_spl_autoloader) || $mailchimp_woocommerce_spl_autoloader === false) {
include_once "bootstrap.php";
}
register_activation_hook( __FILE__, 'activate_mailchimp_woocommerce');
add_action('plugins_loaded', 'mailchimp_on_all_plugins_loaded');
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$forwarded_address = explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']);
$_SERVER['REMOTE_ADDR'] = $forwarded_address[0];
}

View File

@@ -0,0 +1,83 @@
<?php
/**
* The public-facing functionality of the plugin.
*
* @link https://mailchimp.com
* @since 1.0.1
*
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/public
*/
/**
* The public-facing functionality of the plugin.
*
* Defines the plugin name, version, and two examples hooks for how to
* enqueue the admin-specific stylesheet and JavaScript.
*
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/public
* @author Ryan Hungate <ryan@vextras.com>
*/
class MailChimp_WooCommerce_Public {
/**
* The ID of this plugin.
*
* @since 1.0.0
* @access private
* @var string $plugin_name The ID of this plugin.
*/
private $plugin_name;
/**
* The version of this plugin.
*
* @since 1.0.0
* @access private
* @var string $version The current version of this plugin.
*/
private $version;
/**
* Initialize the class and set its properties.
*
* @since 1.0.0
* @param string $plugin_name The name of the plugin.
* @param string $version The version of this plugin.
*/
public function __construct( $plugin_name, $version ) {
$this->plugin_name = $plugin_name;
$this->version = $version;
}
/**
* Register the stylesheets for the public-facing side of the site.
*
* @since 1.0.0
*/
public function enqueue_styles() {
//wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/mailchimp-woocommerce-public.css', array(), $this->version, 'all' );
}
/**
* Register the JavaScript for the public-facing side of the site.
*
* @since 1.0.0
*/
public function enqueue_scripts() {
wp_register_script($this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/mailchimp-woocommerce-public.min.js', array(), $this->version, false);
wp_localize_script($this->plugin_name, 'mailchimp_public_data', array(
'site_url' => site_url(),
'ajax_url' => admin_url('admin-ajax.php'),
));
// Enqueued script with localized data.
wp_enqueue_script($this->plugin_name);
//if we have the connected_site script url saved, we need to inject it
if (($site = mailchimp_get_connected_site_script_url()) && !empty($site)) {
wp_enqueue_script($this->plugin_name.'_connected_site', $site, array(), $this->version, true);
}
}
}

View File

@@ -0,0 +1,4 @@
/**
* All of the CSS for your public-facing functionality should be
* included in this file.
*/

View File

@@ -0,0 +1 @@
<?php // Silence is golden

View File

@@ -0,0 +1,205 @@
var mailchimp,
mailchimp_cart,
mailchimp_billing_email,
mailchimp_username_email,
mailchimp_registration_email,
mailchimp_submitted_email = false,
mailchimpReady = function (a) { /in/.test(document.readyState) ? setTimeout("mailchimpReady(" + a + ")", 9) : a(); };
function mailchimpGetCurrentUserByHash(a) {
try {
var b = mailchimp_public_data.ajax_url + "?action=mailchimp_get_user_by_hash&hash=" + a, c = new XMLHttpRequest;
c.open("POST", b, !0), c.onload = function () {
if (c.status >= 200 && c.status < 400) {
var a = JSON.parse(c.responseText);
if (!a) return;
mailchimp_cart.valueEmail(a.email) && mailchimp_cart.setEmail(a.email);
}
};
c.onerror = function () {
console.log("mailchimp.get_email_by_hash.request.error", c.responseText)
};
c.setRequestHeader("Content-Type", "application/json");
c.setRequestHeader("Accept", "application/json");
c.send();
} catch (a) {
console.log("mailchimp.get_email_by_hash.error", a)
}
}
function mailchimpHandleBillingEmail(selector) {
try {
if (!selector) selector = "#billing_email";
var a = document.querySelector(selector);
var b = void 0 !== a ? a.value : "";
if (!mailchimp_cart.valueEmail(b) || mailchimp_submitted_email === b) { return false; }
mailchimp_cart.setEmail(b);
var c = mailchimp_public_data.ajax_url + "?action=mailchimp_set_user_by_email&email=" + b;
var d = new XMLHttpRequest;
d.open("POST", c, !0);
d.onload = function () {
var successful = d.status >= 200 && d.status < 400;
var msg = successful ? "mailchimp.handle_billing_email.request.success" : "mailchimp.handle_billing_email.request.error";
if (successful) {
mailchimp_submitted_email = b;
}
console.log(msg, d.responseText);
};
d.onerror = function () {
console.log("mailchimp.handle_billing_email.request.error", d.responseText)
};
d.setRequestHeader("Content-Type", "application/json");
d.setRequestHeader("Accept", "application/json");
d.send();
return true;
} catch (a) {
console.log("mailchimp.handle_billing_email.error", a); mailchimp_submitted_email = !1
}
}
!function () {
"use strict";
function mailchimpCart() {
this.email_types = "input[type=email]";
this.regex_email = /^([A-Za-z0-9_+\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
this.current_email = null;
this.previous_email = null;
this.expireUser = function () {
this.current_email = null;
mailchimp.storage.expire("mailchimp.cart.current_email");
};
this.expireSaved = function () {
mailchimp.storage.expire("mailchimp.cart.items");
};
this.setEmail = function (a) {
if (!this.valueEmail(a)) return false;
this.setPreviousEmail(this.getEmail());
mailchimp.storage.set("mailchimp.cart.current_email", this.current_email = a);
};
this.getEmail = function () {
if (this.current_email) return this.current_email;
var a = mailchimp.storage.get("mailchimp.cart.current_email", !1);
if (!a || !this.valueEmail(a)) return false;
return this.current_email = a;
};
this.setPreviousEmail = function (a) {
if (!this.valueEmail(a)) return false;
mailchimp.storage.set("mailchimp.cart.previous_email", this.previous_email = a);
};
this.valueEmail = function (a) {
return this.regex_email.test(a);
};
return this;
}
var g = {
extend: function (a, b) {
for (var c in b || {})b.hasOwnProperty(c) && (a[c] = b[c]);
return a
}, getQueryStringVars: function () {
var a = window.location.search || "", b = [], c = {};
if (a = a.substr(1), a.length) {
b = a.split("&");
for (var d in b) {
var e = b[d];
if ("string" == typeof e) {
var f = e.split("="), g = f[0], h = f[1];
g.length && ("undefined" == typeof c[g] && (c[g] = []), c[g].push(h))
}
}
}
return c
}, unEscape: function (a) {
return decodeURIComponent(a)
}, escape: function (a) {
return encodeURIComponent(a)
}, createDate: function (a, b) {
a || (a = 0);
var c = new Date, d = b ? c.getDate() - a : c.getDate() + a;
return c.setDate(d), c
}, arrayUnique: function (a) {
for (var b = a.concat(), c = 0; c < b.length; ++c)for (var d = c + 1; d < b.length; ++d)b[c] === b[d] && b.splice(d, 1);
return b
}, objectCombineUnique: function (a) {
for (var b = a[0], c = 1; c < a.length; c++) {
var d = a[c];
for (var e in d)b[e] = d[e]
}
return b
}
}, h = function (a, b) {
var c = function (a, b, d) {
return 1 === arguments.length ? c.get(a) : c.set(a, b, d)
};
return c.get = function (b, d) {
return a.cookie !== c._cacheString && c._populateCache(), void 0 == c._cache[b] ? d : c._cache[b]
}, c.defaults = {path: "/"}, c.set = function (d, e, f) {
switch (f = {
path: f && f.path || c.defaults.path,
domain: f && f.domain || c.defaults.domain,
expires: f && f.expires || c.defaults.expires,
secure: f && f.secure !== b ? f.secure : c.defaults.secure
}, e === b && (f.expires = -1), typeof f.expires) {
case"number":
f.expires = new Date((new Date).getTime() + 1e3 * f.expires);
break;
case"string":
f.expires = new Date(f.expires)
}
return d = encodeURIComponent(d) + "=" + (e + "").replace(/[^!#-+\--:<-\[\]-~]/g, encodeURIComponent), d += f.path ? ";path=" + f.path : "", d += f.domain ? ";domain=" + f.domain : "", d += f.expires ? ";expires=" + f.expires.toGMTString() : "", d += f.secure ? ";secure" : "", a.cookie = d, c
}, c.expire = function (a, d) {
return c.set(a, b, d)
}, c._populateCache = function () {
c._cache = {};
try {
c._cacheString = a.cookie;
for (var d = c._cacheString.split("; "), e = 0; e < d.length; e++) {
var f = d[e].indexOf("="), g = decodeURIComponent(d[e].substr(0, f)), f = decodeURIComponent(d[e].substr(f + 1));
c._cache[g] === b && (c._cache[g] = f)
}
} catch (a) {
console.log(a)
}
}, c.enabled = function () {
var a = "1" === c.set("cookies.js", "1").get("cookies.js");
return c.expire("cookies.js"), a;
}(), c
}(document);
mailchimp = {storage: h, utils: g};
mailchimp_cart = new mailchimpCart;
}();
mailchimpReady(function () {
if (void 0 === a) {
var a = { site_url: document.location.origin, defaulted: !0, ajax_url: document.location.origin + "/wp-admin?admin-ajax.php" };
}
try {
var b = mailchimp.utils.getQueryStringVars();
void 0 !== b.mc_cart_id && mailchimpGetCurrentUserByHash(b.mc_cart_id);
mailchimp_username_email = document.querySelector("#username");
mailchimp_billing_email = document.querySelector("#billing_email");
mailchimp_registration_email = document.querySelector("#reg_email");
if (mailchimp_billing_email) {
mailchimp_billing_email.onblur = function () { mailchimpHandleBillingEmail('#billing_email'); };
mailchimp_billing_email.onfocus = function () { mailchimpHandleBillingEmail('#billing_email'); }
}
if (mailchimp_username_email) {
mailchimp_username_email.onblur = function () { mailchimpHandleBillingEmail('#username'); };
mailchimp_username_email.onfocus = function () { mailchimpHandleBillingEmail('#username'); }
}
if (mailchimp_registration_email) {
mailchimp_registration_email.onblur = function () { mailchimpHandleBillingEmail('#reg_email'); };
mailchimp_registration_email.onfocus = function () { mailchimpHandleBillingEmail('#reg_email'); }
}
} catch (e) {
console.log('mailchimp ready error', e);
}
});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,16 @@
<?php
/**
* Provide a public-facing view for the plugin
*
* This file is used to markup the public-facing aspects of the plugin.
*
* @link https://mailchimp.com
* @since 1.0.1
*
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/public/partials
*/
?>
<!-- This file should primarily consist of HTML with a little bit of PHP. -->

View File

@@ -0,0 +1,52 @@
<?php
/**
* Fired when the plugin is uninstalled.
*
* When populating this file, consider the following flow
* of control:
*
* - This method should be static
* - Check if the $_REQUEST content actually is the plugin name
* - Run an admin referrer check to make sure it goes through authentication
* - Verify the output of $_GET makes sense
* - Repeat with other user roles. Best directly by using the links/query string parameters.
* - Repeat things for multisite. Once for a single site in the network, once sitewide.
*
* This file may be updated more in future version of the Boilerplate; however, this is the
* general skeleton and outline for how the file should work.
*
* For more information, see the following discussion:
* https://github.com/tommcfarlin/WordPress-Plugin-Boilerplate/pull/123#issuecomment-28541913
*
* @link https://mailchimp.com
* @since 1.0.1
*
* @package MailChimp_WooCommerce
*/
// If uninstall not called from WordPress, then exit.
if (!defined( 'WP_UNINSTALL_PLUGIN')) {
exit;
}
if (!isset($mailchimp_woocommerce_spl_autoloader) || $mailchimp_woocommerce_spl_autoloader === false) {
include_once "bootstrap.php";
}
try {
if (($options = get_option('mailchimp-woocommerce', false)) && is_array($options)) {
if (isset($options['mailchimp_api_key'])) {
$store_id = get_option('mailchimp-woocommerce-store_id', false);
if (!empty($store_id)) {
$api = new MailChimp_WooCommerce_MailChimpApi($options['mailchimp_api_key']);
$result = $api->deleteStore($store_id) ? 'has been deleted' : 'did not delete';
error_log("store id {$store_id} {$result} MailChimp");
}
}
}
} catch (\Exception $e) {
error_log($e->getMessage().' on '.$e->getLine().' in '.$e->getFile());
}
mailchimp_clean_database();