Выбирайте правильный механизм хранения данных.

Операции с базой данных очень часто становятся узким местом при реализации веб проекта. Вопросы оптимизации в таких случаях касаются не только администратора базы данных. Программистам нужно правильно выполнять структурирование таблиц, писать оптимальные запросы и более производительный код. В данной статье приводится небольшой список техник оптимизации работы с MySQL для программистов.

1. Оптимизируйте ваши запросы для кэша запросов.

Большинство серверов MySQL используют кэширование запросов. Это один из эффективных методов улучшения производительности, который выполняется механизмом базы данных в фоновом режиме. Если запрос выполняется много раз, то для получения результата начинает использоваться кэш и операция выполняется значительно быстрее.

Проблема заключается в том, что это так просто и в то же время скрыто от разработчика, и большинство программистов игнорирует такую прекрасную возможность улучшить производительность проекта. Некоторые действия в действительности могут создавать препятствия для использования кэша запросов при выполнении.

// Кэш запроса НЕ РАБОТАЕТ $r = mysql_query("SELECT username FROM user WHERE signup_date >= CURDATE()"); // Кэш запроса РАБОТАЕТ! $today = date("Y-m-d"); $r = mysql_query("SELECT username FROM user WHERE signup_date >= "$today"");

Причина того, что кэш запросов не работает в первом случае, заключается в использовании функции CURDATE() . Такой подход используется для всех недетерминированных функций, например, NOW(), RAND() и т.д. Так как возвращаемый результат функции может измениться, то MySQL решает не размещать данный запрос в кэше. Все что, нужно, чтобы исправить ситуацию - это добавить дополнительную строчку кода PHP перед запросом.

2. Используйте EXPLAIN для ваших запросов SELECT

Использование ключевого слова EXPLAIN может помочь составить картину того, что делает MySQL для выполнения вашего запроса. Такая картина позволяет легко выявить узкие места и другие проблемы в запросах или структуре таблиц.

Результат запроса EXPLAIN показывает, какие индексы используются, как таблица сканируется и сортируется, и так далее.

Возьмем запрос SELECT (предпочтительно, чтобы он был сложным, с JOIN), добавим перед ним ключевое слово EXPLAIN. Вы можете использовать PhpMyAdmin для этого. Такой запрос выведет результат в прекрасную таблицу. Допустим, мы забыли добавить индекс для столбца, который используется для JOIN:

После добавления индекса для поля group_id:

Теперь вместо сканирования 7883 строк, будут сканироваться только 9 и 16 строк из двух таблиц. Хорошим методом оценки производительности является умножение всех чисел в столбце “rows”. Результат примерно пропорционален прорабатываемому объему данных.

3. Используйте LIMIT 1, если нужно получить уникальную строку

Иногда, во время использования запроса, вы уже знаете, что ищете только одну строку. Вы можете получить уникальную запись или просто проверить существование любого количества записей, которые удовлетворяют предложению WHERE.

В таком случае добавление LIMIT 1 к вашему запросу может улучшить производительность. При таком условии механизм базы данных останавливает сканирование записей как только найдет одну и не будет проходит по всей таблице или индексу.

// Есть ли какой нибудь пользователь из Алабамы? // Так не нужно делать: $r = mysql_query("SELECT * FROM user WHERE state = "Alabama""); if (mysql_num_rows($r) > 0) { // ... } // Вот так будет значительно лучше: $r = mysql_query("SELECT 1 FROM user WHERE state = "Alabama" LIMIT 1"); if (mysql_num_rows($r) > 0) { // ... }

4. Индексируйте поля поиска

Индексируйте не только основные и уникальные ключи. Если какие-нибудь столбцы в вашей таблице используются для поисковых запросов, то их нужно индексировать.

Как вы можете видеть, данное правило применимо и к поиску по части строки, например, “last_name LIKE ‘a%’”. Когда для поиска используется начало строки, MySQL может использовать индекс столбца, по которому проводится поиск.

Вам также следует разобраться, для каких видов поиска нельзя использовать обычное индексирование. Например, при поиске слова (“WHERE post_content LIKE ‘%apple%’”) преимущества индексирования будут не доступны. В таких случая лучше использовать полнотекстовый поиск mysql или построение собственных решений на основе индексирования.

5. Индексирование и использование одинаковых типов для связываемых столбцов

Если ваше приложение содержит много запросов с директивой JOIN, вам нужно индексировать столбцы, которые связываются в обеих таблицах. Это оказывает эффект на внутреннюю оптимизацию операций связывания в MySQL.

Также связываемые столбцы должны иметь одинаковый тип. Например, если вы связываете столбец DECIMAL со столбцом INT из другой таблицы, MySQL не сможет использовать индекс по крайней мере для одной из двух таблиц. Даже кодировка символов должна быть одинаковой для одинаковых столбцов строчного типа.

// Поиск компании из определенного штата $r = mysql_query("SELECT company_name FROM users LEFT JOIN companies ON (users.state = companies.state) WHERE users.id = $user_id"); // оба столбца для названия штата должны быть индексированы // и оба должны иметь одинаковый тип и кодировку символов // или MySQL проведет полное сканирование таблицы

6. Не используйте ORDER BY RAND()

Это один их тех трюков, которые круто выглядят, и многие начинающие программисты попадают в его ловушку. Они даже представить не могут, какую ужасную проблему сами себе создают, начав использовать это выражение в своих запросах.

Если вам действительно нужно случайным образом располагать строки в результате вашего запроса, то существует множество лучших способов решить такую задачу. Конечно, это будет реализовано дополнительным кодом, но вы будете спасены от проблемы, которая растет по экспоненциальному закону вместе с ростом объема данных. Дело в том, что MySQL выполняет операцию RAND() (которая занимает время процессора) для каждой отдельной строки в таблице перед тем, как отсортировать ее и выдать вам только одну строку.

// Так делать НЕ НУЖНО: $r = mysql_query("SELECT username FROM user ORDER BY RAND() LIMIT 1"); // Вот так будет лучше работать: $r = mysql_query("SELECT count(*) FROM user"); $d = mysql_fetch_row($r); $rand = mt_rand(0,$d - 1); $r = mysql_query("SELECT username FROM user LIMIT $rand, 1");

Так вы получаете случайное число, которое меньше, чем количество строк в результате запроса, и используете его как смещение в предложении LIMIT.

7. Старайтесь не использовать SELECT *

Чем больше данных будет прочитано из таблицы, тем медленнее выполняется запрос. Такие операции также занимают время для выполнения дисковых операций. А если сервер базы данных отделен от веб-сервера, то задержки будут вызваны еще и передачей данных по сети между серверами.

Хорошей привычкой является указание столбца при выполнении SELECT.

// Плохо: $r = mysql_query("SELECT * FROM user WHERE user_id = 1"); $d = mysql_fetch_assoc($r); echo "Welcome {$d["username"]}"; // Так лучше: $r = mysql_query("SELECT username FROM user WHERE user_id = 1"); $d = mysql_fetch_assoc($r); echo "Welcome {$d["username"]}"; // Разница становится существенной на больших объемах данных

8. Старайтесь использовать поле id везде

Хорошей практикой является использование в каждой таблице поля id, для которого установлены свойства PRIMARY KEY, AUTO_INCREMENT, и оно имеет тип из семейства INT. Предпочтительно - UNSIGNED, так как в этом случае значение не может быть отрицательным.

Даже если в вашей таблице есть поле с уникальным именем пользователя, не делайте его основным ключом. Поля с типом VARCHAR медленно работают в качестве основных ключей. Также структура вашей базы данных будет лучше, если в ней внутри использовать ссылки на записи на основании id.

Кроме того механизм MySQL использует основные ключи для своих внутренних задач, и использование поля id создает оптимальные условия для их решения.

Одним возможным исключением из данного правила являются “ассоциативные таблицы”, которые используются для отношений многие-ко-многим между двумя другими таблицами. Например, таблица “posts_tags” содержит 2 столбца: post_id, tag_id. Они используются для описания отношений между двумя таблицами “post” и “tags”. Описанная таблица может иметь основной ключ, который содержит оба поля id.

9. Используйте ENUM вместо VARCHAR

// Создаем подготовленное выражение if ($stmt = $mysqli->prepare("SELECT username FROM user WHERE state=?")) { // Привязываем параметры $stmt->bind_param("s", $state); // Выполняем $stmt->execute(); // Привязываем переменные результата $stmt->bind_result($username); // Получаем значения $stmt->fetch(); printf("%s is from %s\n", $username, $state); $stmt->close(); }

13. Небуферированные запросы

Обычно, когда вы выполняете запрос из скрипта, то работа скрипта прерывается до тех пор, пока запрос не будет выполнен. Такой порядок действий можно изменить с помощью небуферированных запросов.

Отличное объяснение функции mysql_unbuffered_query() из документации PHP:

“mysql_unbuffered_query() отправляет SQL запрос на сервер MySQL без автоматического получения и буферирования строк результата, как это делает функция mysql_query(). Таким образом, сохраняется определенный объем памяти запросами SQL, которые выдают большой набор результата, и можно начинать работать с набором результата сразу же после получения первой строки, не дожидаясь пока запрос SQL будет полностью выполнен.”

Однако существует несколько ограничений. Вы должны либо прочитать все строки либо вызвать mysql_free_result() перед тем, как выполнить следующий запрос. Также нельзя использовать mysql_num_rows() или mysql_data_seek() для набора результата.

14. Храните IP адрес как UNSIGNED INT

Многие программисты создают поле VARCHAR(15) для хранения IP адреса, даже не задумываясь о том, что будут хранить в этом поле целочисленное значение. Если использовать INT, то размер поля сократится до 4 байт, и оно будет иметь фиксированную длину.

Нужно использовать тип UNSIGNED INT, так как IP адрес задействует все 32 бита беззнакового целого.

$r = "UPDATE users SET ip = INET_ATON("{$_SERVER["REMOTE_ADDR"]}") WHERE user_id = $user_id";

15. Таблицы с фиксированной длиной записи (Static) работают быстрее

Когда каждый отдельный столбец в таблице имеет фиксированную длину, то вся таблица в целом рассматривается как “static” или “с фиксированной длиной записи” . Примеры типов столбцов, которые не имеют фиксированной длины: VARCHAR, TEXT, BLOB. Если вы включите хотя бы один столбец с таким типом, то таблица перестает рассматриваться как "static" и будет по-другому обрабатываться механизмом MySQL.

Таблицы "static" быстрее обрабатываются механизмом MySQL при поиске записей. Когда нужно прочитать определенную запись в таблице, то ее положение быстро вычисляется. Если размер строки не фиксирован, то для определения положения записи нужно время на поиск и сопоставление с индексом основного ключа.

Такие таблицы также проще кэшировать и проще восстанавливать при сбоях. Но они могут занимать больше места. Например, если конвертировать поле VARCHAR(20) в поле CHAR(20), то всегда будут заняты 20 байт вне зависимости от того, используются они или нет.

Использование техники "Вертикальное разделение" дает возможность отделить столбцы с переменной длиной в отдельную таблицу.

16. Вертикальное разделение

Вертикальное разделение - это действие по разделению структуры таблицы по вертикали с целью оптимизации.

Пример 1 : У вас есть таблица, которая содержит домашние адреса, редко используемые в приложении. Вы можете разделить вашу таблицу и хранить адреса в отдельной таблице. Таким образом основная таблица пользователей сократится в размере. А как известно, меньшая таблица обрабатывается быстрее.

Пример 2 : У вас в таблице есть поле “last_login”. Оно обновляется каждый раз, когда пользователь регистрируется на сайте. Но каждое обновление таблицы вызывает кэширование запроса, что может создать перегрузку системы. Вы можете выделить данное поле в другую таблицу, чтобы сделать обновления таблицы пользователей не такими частыми.

Но надо быть уверенными в том, что не потребуется постоянного связывания двух таблиц, которые вы только что разделили, так как это может привести к ухудшению производительности.

17. Разделяйте большие запросы DELETE или INSERT

Если вам нужно выполнить большой запрос DELETE или INSERT на работающем сайте, то нужно быть осторожным, чтобы не нарушить трафик. Когда выполняется большой запрос, то он может заблокировать ваши таблицы и привести к остановке приложения.

Apache выполняет много параллельных процессов/потоков. по этой причине он работает более эффективно, когда скрипт заканчивает выполнение как можно быстрее, таким образом сервер не использует слишком много открытых соединений и процессов, потребляющих ресурсы, особенно память.

Если вы блокируете таблицы на продолжительное время (например, на 30 и более секунд) на высоко нагруженном веб сервере, вы можете вызвать накапливание процессов и запросов, что потребует значительного времени на расчистку или даже приведет к остановке вашего веб сервера.

Если у вас есть скрипт, который удаляет большое количество записей, просто используйте предложение LIMIT для разбиения его на маленькие партии, чтобы избежать описанной ситуации.

While (1) { mysql_query("DELETE FROM logs WHERE log_date <= "2009-10-01" LIMIT 10000"); if (mysql_affected_rows() == 0) { // выполняем удаление break; } // вы можете сделать небольшую паузу usleep(50000); }

18. Маленькие столбцы обрабатываются быстрее

Для механизма базы данных диск является наиболее важным узким местом. Стремление сделать все более компактным и маленьким обычно хорошо сказывается в сфере производительности за счет сокращения объема перемещаемых данных.

Документация MySQL содержит список норм хранения данных для всех типов.

Если таблица будет содержать всего несколько строк, то нет причин делать основной ключ типа INT, а не MEDIUMINT, SMALLINT или даже TINYINT. если вам нужна только дата, используйте DATE вместо DATETIME.

Нужно только помнить о возможностях роста.

19. Выбирайте правильный механизм хранения данных

Есть два основных механизма хранения данных для MySQL: MyISAM и InnoDB. Каждый имеет свои достоинства и недостатки.

MyISAM отлично подходит для приложений с большой нагрузкой по чтению, но он не очень хорошо масштабируется при наличии большого количества записей. Даже если вы обновляете одно поле в одной строке, вся таблица будет заблокирована и ни один процесс не сможет ничего прочитать пока запрос не завершится. MyISAM быстро выполняет вычисления для запросов типа SELECT COUNT(*).

InnoDB является более сложным механизмом хранения данных, и он может быть более медленным, чем MyISAM для большинства маленьких приложений. Но он поддерживает блокирование строк, что лучше для масштабирования таблиц. Также он поддерживает некоторые дополнительные особенности, такие как транзакции.

20. Используйте объектно-реляционное отображение

Использование объектно-реляционного отображения (ORM - Object Relational Mapper) дает ряд преимуществ. Все, что можно сделать в ORM , можно сделать вручную, но с большими усилиями и более высокими требованиями к уровню разработчика.

ORM отлично подходит для "ленивой загрузки". Это означает, что получение значений возможно тогда, когда они нужны. Но нужно быть аккуратным, потому что можно создать много маленьких запросов, которые понизят производительность.

ORM может также объединять ваши запросы в транзакции, которые выполняются существенно быстрее, чем индивидуальные запросы к базе данных.

Для PHP можно использовать ORM Doctrine .

21. Будьте осторожны с постоянными соединениями

Постоянные соединения предназначены для сокращения потерь на восстановление соединений к MySQL. Когда создается постоянное соединение, то оно остается открытым даже после завершения скрипта. Так как Apache повторно использует дочерние процессы, то процесс выполняется для нового скрипта, и он использует тоже соединение с MySQL.

Это звучит здорово в теории. Но в действительности это функция не стоит медного гроша из-за проблем. Она может вызывать серьезные неприятности с ограничениями количества соединений, переполнение памяти и так далее.

Apache работает на принципах параллельности, и создает множество дочерних процессов. Вот в чем заключается причина того, что постоянные соединения не работают как ожидается в данной системе. Прежде, чем использовать функцию mysql_pconnect(), проконсультируйтесь с вашим системным администратором.

The most complete member management and membership subscriptions plugin for WordPress

Paid Memberships Pro is designed for premium content sites, clubs/associations, subscription products, newsletters and more! The plugin adds a new revenue source to your site and is flexible enough to fit the needs of almost all online and offline businesses.

Simple to install and get running – deeply customizable!

  • Unlimited Levels with Flexible Membership Pricing
  • 6 Popular Payment Gateways Included
  • Extensive Options for Content Restriction
  • Customizable Reports and Member Dashboards
  • Over 60 Premium Add Ons to Extend and Customize
  • 100% GPL and Integrated with Third Party Services

Sites running Paid Memberships Pro use it to:

  • Manage professional organizations with thousands of members.
  • Get paid for e-learning and digital courseware.
  • Accept recurring payment for content, podcasts, video, and more.
  • Create private social communities for unique interest groups.
  • Develop robust directory or listings sites by topic or region.
  • Offer product subscriptions or members-only product discounts.

Choose from Top Payment Gateways.

All of our payment gateways are included in the plugin. Choose from PayPal, Stripe, Authorize.net, Braintree or 2Checkout.

Infinitely Configurable, Unlimited Membership Levels.

Set up the membership levels that best fit your business, whether they are one-time payments or recurring subscriptions (annual, monthly, weekly, daily). You can even offer custom trial periods including Free Trials, Custom-length Trial, or ‘Introductory’ Pricing trials.

Membership levels provide restricted access to members-only content (including pages, posts, categories, videos, forums, downloads, support, single «a la carte» page access, and more).

Control the user-experience from start to finish.

Your members can update their billing information or cancel their account directly on your site. Any active subscription will be cancelled at the payment gateway for you.

Add Ons to help you do more.

Extend the features of your membership site or integrate with third-party services through our library of over 60 add ons. Our library of free or paid Add Ons allow you to:

  • Integrate members with email marketing platforms including Mailchimp, Constant Contact, AWeber and GetResponse.
  • Restrict access to forums, groups, courses, downloads, events, and product.
  • Allow affiliates to get credit for membership checkouts.

Paid Memberships Pro is a free membership plugin for WordPress

Our plugin is 100% GPL and available from the WordPress repository or on our site at http://www.paidmembershipspro.com. The full version of the plugin is offered with no restrictions or additional licenses required. Developers should get involved at our GitHub page .

Скриншоты

Блоки

Этот плагин предоставляет 13 блоков.

Pmpro/membership Require Membership Block pmpro/cancel-page Membership Cancel Page pmpro/account-page Membership Account Page pmpro/levels-page Membership Levels List pmpro/account-profile-section Membership Account: Profile pmpro/checkout-page Membership Checkout Form pmpro/account-membership-section Membership Account: Memberships pmpro/billing-page Membership Billing Page pmpro/account-links-section Membership Account: Links pmpro/account-invoices-section Membership Account: Invoices pmpro/invoice-page Membership Invoice Page pmpro/checkout-button Membership Checkout Button pmpro/confirmation-page Membership Confirmation Page

Часто задаваемые вопросы

I need help installing, configuring, or customizing the plugin.

Отзывы

Have been struggling to use Memberlite theme and the paid memberships pro plugin but find them too restrictive. The member-navigation menu only has 2 levels. Paid support is expensive as are the Pro versions. I’ve gone over to Astra theme with AR-member plugin which is only $20 USD. It works brilliantly and has many levels of menu! Would highly recommend this combination for membership/restricted content

Every time we try to register, it comes up with: There are JavaScript errors on the page. Please contact the webmaster. However, after extensive checking, there are no issues on my site. I have deactivated all plugins and themes and it makes no difference. ***UPDATE*** One of my plugins that deals with AMP and web applications had Optimise Javascript enabled and even when the plugin itself was disabled, the optimisation remained, once I turned this off, it worked fine.

I started using PMPro years ago with one of my first clients. Recently began working on a new membership site. PMPro has great documentation, but I had a question that wasn"t covered in the docs. Sent a support request, and had a reply in my inbox the next morning. They are so helpful, and have been working hard on expanding and improving their product for years. Great work all!

Участники и разработчики

«Paid Memberships Pro» - проект с открытым исходным кодом. В развитие плагина внесли свой вклад следующие участники:

Участники

Журнал изменений

2.0.7 — 2019-05-30

  • BUG FIX: Fixed issue where the profile start date would sometimes be set incorrectly on the Stripe subscription.
  • BUG FIX: Fixed issue where the membership shortcode would not work properly if more than one level name was given.
  • BUG FIX: Fixed issue where an incorrect email address was sometimes set in the confirm email field on the update billing page. (Thanks, Jessica Thomas)
  • BUG FIX/ENHANCEMENT: Fixed placement of the hr tag above the user fields at checkout for consistency.
  • ENHANCEMENT: Set the priority on the Require Membership meta box to «high» so it appears higher in the right sidebar.

2.0.6 — 2019-05-30

  • SECURITY: Now using wp_safe_redirect when possible, especially in includes/login.php where the user-provided redirect_to URL parameter is used. (Thanks PluginVulnerabilities.com)

2.0.5 — 2019-04-25

  • BUG FIX: Fixed fatal error on return from 2Checkout.
  • BUG FIX: Removed error when installing PMPro via WP-CLI.
  • BUG FIX: Fix database upgrade error on localhost environment. (Thanks, codezz on GitHub)
  • BUG FIX: Fixed issue where the credit card expiring email didn’t include user info because the user ID wasn’t passed in properly. (Thanks, David Cervantes Caballero)
  • BUG FIX: Fixed typo on edit level page. (Thanks, Theuns Coetzee)
  • BUG FIX: Fixed bug with daily revenue reports not showing up in some cases.
  • BUG FIX: Now checking before cancelling a Stripe subscription at the gateway to see if it has already been cancelled.
  • BUG FIX/ENHANCEMENT: Now caching the query results in pmpro_getMembershipLevelsForUser(). This improves performance, especially when there are many posts on one page to check membership for. (Thanks, Seagyn Davis)
  • BUG FIX/ENHANCEMENT: Now sending display_name to the $data array passed to PMPro email filters. (Thanks, David Cervantes Caballero)
  • BUG FIX/ENHANCEMENT: Now searching for the last order with «success» or «pending» status on the Billing page.
  • BUG FIX/ENHANCEMENT: Added pmpro_checkout_preheader_before_get_level_at_checkout and pmpro_checkout_preheader_after_get_level_at_checkout action hooks. Using pmpro_checkout_preheader_before_get_level_at_checkout to start the session earlier now.
  • BUG FIX/ENHANCEMENT: Removed the «membership_code_id» and «membership_code» as field options for the member shortcode. These weren’t working and it’s unclear what would be meant to ask for a user’s discount code since a user could have several orders with or without discount codes. Added «membership_description» and «membership_confirmation» instead.
  • BUG FIX/ENHANCEMENT: Filtering the password reset message to make sure the link still works in all cases when we convert emails to HTML.
  • BUG FIX/ENHANCEMENT: Added reCAPTCHA v3 and invisible reCAPTCHA support. It is recommended sites using Stripe or Braintree update to the reCAPTCHA v3 option. Read more here: https://www.paidmembershipspro.com/pmpro-update-2-0-5/
  • REFACTOR: Now running the pmpro_billing_preheader hook after the jquery.creditCardValidator script is enqueued in preheader/billing.php to match how we do it in preheader/checkout.php. (Thanks, Rafe Colton)

2.0.4 — 2019-01-14

  • BUG FIX: Fixed warning in code added in 2.0.3 that could cause issues at checkout.
  • BUG FIX: Setting priority of pmpro_check_admin_capabilities to 5 to ensure it runs before dashboard redirect.
  • BUG FIX: Removed duplicate id attribute on the Membership Account page «cancel» action link.
  • BUG FIX/PERFORMANCE: No longer enqueueing frontend.blocks.js which had no functional code, but loaded a lot of Gutenberg JS that wasn’t needed on the frontend. When/if our blogs have frontend JS, we will load it again, but also make sure the dependencies are correct.
  • BUG FIX/PERFORMANCE: No longer loading blocks.style.css. These frontend styles were redundant with CSS in css/frontend.css.
  • NOTE: The SVN repository was missing the 2.0.3 tag when that update went out. Some users may have updated or tried to update and not gotten the correct files for 2.0.3. Everyone should update to 2.0.4, which is Gucci.

2.0.3 — 2019-01-11

  • BUG FIX: Fixed issue where code in the Stripe gateway was cancelling old subscriptions early if users renewed with a different gateway. NOTE: There was a fix for this in version 2.0, but it wasn’t implemented fully.
  • BUG FIX: Filtering pmpro_other_order_ids_to_cancel to make sure the current checkout’s order doesn’t get cancelled. This started happening in version 2.0 since we started setting the user_id on orders for existing users before the checkout was fully processed. This fix along with the one above and others will fix cases where users were being cancelled immediately after checkout.
  • BUG FIX: Fixed warning on edit levels page by defaulting $confirmation_in_email to 0.

2.0.2 — 2019-01-10

  • BUG FIX: Fixed issues when using non-US currencies. Using the pmpro_round_price function in a few places it was needed. Prepared for a later update that will increase the number of decimals on certain columns in the DB to 8 to support currencies like Bitcoin, but shelving the actual DB update for version 2.1.
  • BUG FIX: Fixed issue where existing users who checked out could run into problems. Added a getMembershipLevelAtCheckout method to the MemberOrder class and using that during checkout. The getMembershipLevel method would see the user_id property of the order (added to orders at checkout in version 2.0) and lookup the level data from the pmpro_memberships_users table instead of using the pmpro_level global. Then gateways like PayPal Express (but others also) would use the wrong data when making calls to pmpro_isLevelRecurring/etc.
  • BUG FIX: Fixed bug where a notice to deactivate the Better Logins Report plugin could show up for users who couldn’t deactive the plugin.
  • BUG FIX: Fixed bad translation in the membership_expired.html file of the French translation.
  • BUG FIX: Fixed some strings on updated reports that weren’t wrapped for translation.

2.0.1 — 2019-01-03

  • BUG FIX: Fixed issue where the PMPro dashboard and reports pages would appear blank if certain other plugins were active.

2.0 — 2018-12-31

  • SECURITY: Fixing how we escape things in the Memberships report SQL queries.
  • BUG FIX: Fixed issue where code in the Stripe gateway was cancelling old subscriptions early if users renewed with a different gateway.
  • BUG FIX: Fixed a warning on the Stripe Webhook service.
  • BUG FIX/ENHANCEMENT: Removing unused images from core plugin.
  • BUG FIX/ENHANCEMENT: Removed unused getTimestamp function.
  • BUG FIX/ENHANCEMENT: Updated Braintree/PHP Library to 3.36.0
  • BUG FIX/ENHANCEMENT: Prefixing Braintree plan name with pmpro_#
  • BUG FIX/ENHANCEMENT: Better table naming in queries for Memberships and Sales reports.
  • BUG FIX/ENHANCEMENT: Changing «blacklist» to «blocklist».
  • BUG FIX/ENHANCEMENT: Changing the appearance of the Discount Code «Apply» button on checkout to look more like a text link.
  • BUG FIX/ENHANCEMENT: Now calculating the next payment date with time, not SQL.
  • BUG FIX/ENHANCEMENT: Updated the pmpro_next_payment method of Stripe to check if a customer is delinquent to avoid returning a next payment date in the future if the last payment failed.
  • BUG FIX/ENHANCEMENT: Saving user ID in MemberOrder when a user already exists and they are checking out via an offsite gateway.
  • BUG FIX/ENHANCEMENT: Updating Stripe Webhook and PayPal IPN Handler to send the cancelled level ID for better cancellation emails.
  • BUG FIX/ENHANCEMENT: Brought back the Stripe Billing limit warnings. Here is a plugin to get billing limits working with Stripe https://github.com/strangerstudios/pmpro-stripe-billing-limits/blob/master/pmpro-stripe-billing-limits.php
  • FEATURE: Gutenberg / v5.0 Editor Blocks for Paid Memberships Pro pages, the Checkout Button and Membership «shortcode» functionality.
  • FEATURE: Added new «Dashboard» page and adjusted the entire menu structure for «Memberships».
  • FEATURE: Created new compatibility checks and included compatability functions for Beaver Builder, Elementor, and SiteOrigin Page Builder.
  • FEATURE: Added REST API routes for post membership access, and user membership level.
  • FEATURE: Added option to include the level’s Confirmation Message in the Confirmation Email.
  • FEATURE: Added a filter by discount code to Memberships and Sales reports.
  • FEATURE: Added a filter by discount code to the Orders admin page.
  • FEATURE: Added a «Copy» option to discount codes.
  • FEATURE: Now allowing you to edit or add a discount code to a single Order edit.
  • FEATURE: Added the ability to export orders by discount code used.
  • FEATURE: Added new file for deprecated functions or hooks.
  • ENHANCEMENT: Moved «Memberships» menu page up in sidebar below Comments.
  • ENHANCEMENT: Replaced the Visits, Views, Logins report with the «Better Logins Report» Add On functionality.
  • ENHANCEMENT: Updating reports that use the Google Charts library to use the updated chart library (corechart.js).
  • ENHANCEMENT: Reports admin page is now loading reports via the add_meta_box WordPress function.
  • ENHANCEMENT: Added ability to filter membership reports for free or paid levels only.
  • ENHANCEMENT: Setting a default level at checkout so that the page doesn’t redirect to the Levels page.
  • ENHANCEMENT: Showing the discount code used on the All Orders and single Order edit page.
  • ENHANCEMENT: Added ability to filter Orders by Free (Orders equal to $0), Paid (Orders greater than $0)
  • ENHANCEMENT: Now showing the Invoice’s Order Status on the Membership Account page for orders (Paid, Pending or Refunded).
  • ENHANCEMENT: Adding additional quick search links when no members are found in members list search.
  • ENHANCEMENT: Added a check on the Add Ons page to hide Add Ons that are no longer supported or recommended.
  • ENHANCEMENT: Improved Responsive layout of the Memberships admin area for smaller devices.
  • ENHANCEMENT: Adding .gitattributes and gitignore. Important now for node stuff in particular.

1.9.5.6 — 2018-11-15

  • BUG FIX: Fixed issue where Braintree would try to cancel a subscription twice if it was cancelled on the Braintree side.
  • BUG FIX: Fixed bug in Braintree webhook when using certain versions of PHP.
  • BUG FIX: Correct Braintree plans flagged as faulty.
  • BUG FIX/ENHANCEMENT: Added Order Code to the Orders Export CSV
  • BUG FIX/ENHANCEMENT: Removed another warning RE billing limits with the Stripe gateway. (Thanks, Jordan Kohl)
  • ENHANCEMENT: Added the pmpro_include_pricing_fields filter.
  • ENHANCEMENT: Adding IDs to action links in the account shortcode so users can target them with CSS/JS.
  • ENHANCEMENT: Updated French Translation. (Thanks, Pascal)
  • ENHANCEMENT: Retina logo on dashboard pages.
  • ENHANCEMENT: Showing what PMPro page a page is in the Post List table of the WP dashboard.

1.9.5.5 — 2018-10-19

  • BUG FIX: Fixed fatal error in the Braintree webhook that will have caused syncing issues for Braintree users.
  • BUG FIX: Stopped sending the cancel subscription request to the PayPal API if we are processing the IPN request for the same subscription.
  • BUG FIX: Fixed issue where the Stripe API version was shown for non-Stripe gateways on the payment settings page.
  • BUG FIX: Using self:: instead of static:: in the Stripe class that could keep the pmpro_stripe_customerid from being updated.
  • BUG FIX: Fixed some fatal errors in PHP 5.2. (We still recommend a minimum PHP 5.6.)
  • BUG FIX/ENHANCEMENT: Removed a unnecessary hr element when viewing the table of all active memberships.
  • BUG FIX/ENHANCEMENT: Cleaned up some CSS code around buttons.
  • BUG FIX/ENHANCEMENT: Added formatting for the Danish Krone.
  • BUG FIX/ENHANCEMENT: Removed the warning RE billing limits with the Stripe gateway. Our Stripe implementation has actually supported billing limits for a while.
  • ENHANCEMENT: Added Kenyan Shilling as a currency. (Thanks, Urandu Bildad Namawa)
  • ENHANCEMENT: Updated the description, url, email, and copyright info in the plugin header.
  • ENHANCEMENT: Now showing a note on the pages list in the dashboard if a page is linked to a PMPro page.
  • ENHANCEMENT: Improving logo and watermark in the dashboard for retina displays.

1.9.5.4 — 2018-09-10

  • SECURITY: Some values used in SQL queries in our reporting code were sanitized but not later escaped via esc_sql(). All variables added to SQL queries in the reports are now wrapped in esc_sql(). The previous code was not vulnerable to any known attack, but this change hardens the code against vulnerabilities in the case other parts of the code change in the future.
  • BUG FIX: Fixed issue with lost passwords when Theme My Login 7 is active. (Thanks, Jeff Farthing)
  • BUG FIX: No longer sending an «error canceling the subscription» email when subscriptions are cancelled from Stripe.
  • BUG FIX: Fixed issue where TwoCheckout orders were not correctly updating the TOS consent data. (Thanks, Charl P. Botha)
  • BUG FIX: Fixed issue where privacy function weren’t defaulting to $current_user correctly. In practice, we were always passing a user_id anyway.
  • BUG FIX/ENHANCEMENT: Changed the confirmation message to use wpautop instead of apply_filters(‘the_content’). If you were relying on shortcodes or other content that required that filter, you use add_filter(‘pmpro_level_description’, ‘the_content’) to revert this for your site.
  • BUG FIX/ENHANCEMENT: Using the strict parameter of sanitize_user when getting usernames. This will prevent some special characters from being used in usernames at checkout. This is inline with WP core and other plugins. (Thanks, David Cervantes Caballero)
  • ENHANCEMENT: Added a breakdown of orders at each price point to the Sales Report widget
  • ENHANCEMENT: Showing the Stripe version we use on the Payment Settings page.
  • ENHANCEMENT: Updated Copyright date and GPLv2 link in license.txt.

1.9.5.3 — 2018-06-26

  • BUG FIX: The pmpro_ipnhandler_extend_memberships function actually needed use $user_id instead of $current_user.

1.9.5.2 — 2018-06-26

  • BUG FIX: Fixed compatibility with Theme My Login version 7. (Thanks, Jeff Farthing)
  • BUG FIX: Fixed missing $current_user bug in pmpro_ipnhandler_level_extend_memberships function. (Thanks, Anne)

1.9.5.1 — 2018-06-08

  • BUG FIX: Fixed issue with the PayPal IPN Handler where existing users checking out for a new level would sometimes have their membership and new subscription cancelled.
  • BUG FIX: Fixed PayPal IPN Handler to set the status of old levels to ‘changed’ (instead of ‘inactive’) when processing checkouts. This will improve the accuracy of reports.
  • BUG FIX/ENHANCEMENT: Now checking for the recurring_payment_skipped transaction type in the PayPal IPN handler. When a payment is skipped and this message is sent, we will now fire off the failed payment email to the customer and admin. (Thanks, mjulian87 on GitHub)
  • ENHANCEMENT: Removed validation info from the IPN log.
  • ENHANCEMENT: Updated German (de_DE) language files.

1.9.5 — 2018-05-24

  • BUG FIX: Added ‘error’ to the list of default order statuses.
  • BUG FIX: Fixed issue where PayPal recurring_payment messages with status «Pending» were treated as «Failed» by our IPN handler. (Thanks, Matt Julian)
  • BUG FIX: The redirect away from the billing page needed to be in the preheader instead of the page shortcode.
  • BUG FIX/ENHANCEMENT: Using the pmpro_getOrderStatuses() function in adminpages/orders.php instead of redundant code there.
  • BUG FIX/ENHANCEMENT: Passing the $order as a second parameter to pmpro_after_checkout when called from the PayPal IPN handler. (The $order was being passed already for «regular» checkouts.)
  • ENHANCEMENT: You can now sort by the Membership Level column added to the users list in the dashboard. (Thanks, Matt Julian)
  • FEATURE: Added support for the privacy features added in WP 4.9.6. Details below.
  • FEATURE: Added suggest privacy page text.
  • FEATURE: Added PMPro-related user meta fields, membership history, and order history to the personal data export. You can filter which user meta fields are included in the export using the new pmpro_get_personal_user_meta_fields filter.
  • FEATURE: Deleting PMPro-related personal data fields when personal data is erased. The ereaser deletes a number of user meta fields (filterable through the new pmpro_get_personal_user_meta_fields_to_erase filter). A user’s membership history and order history are retained unless the user is deleted.
  • FEATURE: Now saving a log of when the TOS page is agreed to at checkout. The ID and date modified of the TOS post is saved along with a timestamp of when the TOS was agreed to. This information is shown on the single order page in the admin, the orders CSV export, and on the edit user profile page in the admin. Note that this feature does not yet backport any data for existing users or ask users to re-agree to the TOS if the TOS has gone out of date.

1.9.4.4 — 2018-03-14

  • BUG FIX: Updated the filters to extend membership levels to use the new pmpro_getSpecificMembershipLevelForUser() function to avoid bugs when MMPU is enabled.
  • BUG FIX: Fixed cases where certain email templates were resulting in the body of the email being duplicated.
  • BUG FIX: Fixed conflict with pmpro-email-templates when emails were disabled (the pmpro_email filter returns false). (Thanks, Mathieu Hays)
  • BUG FIX: Now updating status on related subscription orders BEFORE canceling at gateway to avoid cases where the webhook sent by the gateway after canceling the subscription triggers further cancellation attempts.
  • BUG FIX: No longer showing the «Stripe Publishable Key appears incorrect» error message if the key field is blank.
  • ENHANCEMENT: Added the pmpro_getSpecificMembershipLevelForUser($user_id, $level_id) function for cases where MMPU is enabled and you want data about a specific membership level a user might have.
  • ENHANCEMENT: Changed labels on the reCAPTCHA settings to match their current terminology: Site Key and Secret Key.

1.9.4.3 — 2018-01-04

  • BUG FIX: Fixed issue where PMPro would attempt to cancel gateway subscriptions more than once in some cases.

1.9.4.2 — 2017-12-07

  • BUG FIX: Avoid double-encoding the API version in PayPal Standard gateway
  • BUG FIX: The update billing page now checks the gateway of the user’s last order instead of the default gateway settings in case multiple gateways are in use or the default gateway has changed.
  • BUG FIX: Fixed bug where discount codes were not being applied properly if the pmpro_default_level custom field was set and used on a page.
  • BUG FIX: Credit card expiration emails were being to sent to members with PayPal Express orders.
  • BUG FIX: Now correctly unslashing instructions for the check gateway.
  • BUG FIX: Fixed issue with creating pages from the page settings page.
  • BUG FIX/ENHANCEMENT: Improved submit button and processing message position for default and RTL on checkout page.
  • BUG FIX/ENHANCEMENT: Added invoice total and total billed breakdown back to confirmation and invoice single views.
  • BUG FIX/ENHANCEMENT: Avoid double-encoding the PayPal API version number
  • ENHANCEMENT: Improved submit button and processing message position for default and RTL on checkout page.
  • ENHANCEMENT: Switched order of Publishable and Secret Key fields and added validation check.
  • ENHANCEMENT: Conditionally update members list headings for expired, cancelled, or old members.

1.9.4.1 — 2017-10-31

  • BUG FIX: Fixed serious bug where payment fields weren’t showing up for the Braintree gateway.
  • BUG FIX: Fixed issue where Braintree webhook notifications were failing. We now allow the Braintree library to sanitize the incoming data since our sanitizing efforts were breaking the validation.
  • BUG FIX/ENHANCEMENT: The webhook URL given for Braintree now goes through admin-ajax.php instead of a direct link to a php file within our plugin.
  • BUG FIX/ENHANCEMENT: Updates to the Recaptcha library. (Thanks, Corin Simpson-Bryars)
  • ENHANCEMENT: Made the cancelation failed error email easier to read.

1.9.4 — 2017-10-26

  • BUG FIX: Fixed issue where PayPal was not working for amounts over $1000.
  • BUG FIX: Non-decimal currencies now handled correctly with Stripe.
  • BUG FIX: Fixed issue where updating a Stripe subscription from the edit user page could cancel the subscription once the webhook fired.
  • BUG FIX: Fixed issue where «admin_cancelled» memberships weren’t being calculated correctly in membership reports.
  • BUG FIX: Fixed issue where users could not drag and drop to change the order of membership levels.
  • BUG FIX: pmpro_getMembershipLevelsForUser() would sometimes return duplicate levels in the array if the user had multiple active entries in the pmpro_memberships_users table.
  • BUG FIX: Updated includes/metaboxes.php to call pmpro_getAllLevels() instead of relying on the $membership_levels global which is problematic.
  • BUG FIX: Fixed a few strings that weren’t wrapped for translation or were using the old text domain.
  • BUG FIX: Fixed redirect error that occured when the levels page was not set.
  • BUG FIX: Updated getfile.php to support file names with urlencoded characters (e.g. spaces) in them. (Thanks, florent from PMPro blog)
  • BUG FIX: Fixed notice when use the getfile.php script due to using add_filter instead of apply_filters in the mimetype class.
  • BUG FIX: Fixed the all time views column for the logins report.
  • BUG FIX: Fixed fatal error on the logins report, member shortcode and other issues when using PHP7.1+.
  • BUG FIX: Fixed issue with saving arrays using pmpro_setOption()
    up the lines of text.
  • BUG FIX: Fixed typo in the string «Are you sure you want to do that? Try again.»
  • BUG FIX: Fixed a few strings that used the wrong text domain or weren’t wrapped correclty for translation.
  • BUG FIX/ENHANCEMENT: Now bundling Google’s jsapi.js file for use in the reports.
  • BUG FIX/ENHANCEMENT: Fixed issue where some emails (e.g. the password reset email) would not have wpautop applied to them, crunching
  • BUG FIX/ENHANCEMENT: Better checking for Theme My Login compatibility when handling login redirects.
  • BUG FIX/ENHANCEMENT: Better error handling for Braintree.
  • BUG FIX/ENHANCEMENT: Membership stats widget now shows first 3 levels based on level order.
  • BUG FIX/ENHANCEMENT: Added the pmpro_member_shortcode_access filter
  • ENHANCEMENT: Updated the Stripe PHP library to version 5.2.2 and updated Stripe to use the latest version of their API, 2017-08-15.
  • ENHANCEMENT: Changed frontend pages (e.g. checkout.php) to use a div-based layout instead of tables. Important information here if you are using custom page templates or notice UI issues after upgrading:
  • ENHANCEMENT: Added pagination to the discount codes page in the admin. Also sorting codes in descending order by ID. Use the pmpro_discount_codes_per_page filter to change the per page limit from 15.
  • ENHANCEMENT: Updated plugin frontend pages checkout, billing, confirmation, and single invoice to remove most table based layouts.
  • ENHANCEMENT: Better error message if trying to checkout using an existing user’s email address.
  • ENHANCEMENT: Added the pmpro_report_levels filter to let users change levels and order of levels for the memberships.php report.
  • ENHANCEMENT: Updated video and copy for readme.txt.
  • ENHANCEMENT: Added user display name to Memberlist search query
  • ENHANCEMENT: Added Russian Ruble as a currency.
  • ENHANCEMENT: Changed the dated term «CVV» to «Security Code (CVC)» when shown on the frontend.
  • ENHANCEMENT: Added .doc and .docx to the mimetype class.
  • ENHANCEMENT: Added Portuguese language files. (Thanks, Secundino Correia)
  • ENHANCEMENT: Updated plugin admin pages with better links to documentation and support.

1.9.3 — 2017-07-06

  • SECURITY: Fixed sanitization of inputs and added nonces in several places to protect against XSS attacks.
  • BUG FIX: Showing correct error message when trying to update a PMPro Plus add on with a Core license installed.
  • BUG FIX: Fixed issue where subscription and payment transaction IDs were not being saved correctly when copying an order in the dashboard. (Thanks, Pippin Williamson)
  • BUG FIX: Fixed fatal errors that occurred in certain PHP versions.
  • BUG FIX: Fixed issue where ProfileStartDate was being calculated incorrectly in the test, check, and Cybersource gateways.(Thanks, David Parker)
  • ENHANCEMENT: Added a pmpro_sanitize_with_safelist() function that is used to sanitize inputs that have a limited number of exact options.
  • ENHANCEMENT: Updated the pmpro_setOption() and pmpro_getParam() functions to take a new last parameter $sanitize_function, which defaults to ‘sanitize_text_field’.

1.9.2.2 — 2017-06-13

  • BUG FIX: Fixed warnings on the Network Dashboard’s sites page.
  • BUG FIX: Skipping update scripts that require the Stripe library if the system doesn’t support the minimum requirements for the Stripe API. This avoids warnings and errors during upgrade.

1.9.2.1 — 2017-06-05

  • BUG FIX: Fixed issues with activation on single sites.
  • BUG FIX: Starting PHP sessions earlier to fix issues with PayPal/PayPal Express checkouts.

1.9.2 — 2017-06-03

  • BUG FIX: Fixed issue where Braintree checkouts were failing with a CVV error when existing users checked out.
  • BUG FIX: Fixed issue loading the Stripe library in PHP 5.6.
  • BUG FIX: Member List CSV export was ignoring search parameter.
  • BUG FIX: Discount codes weren’t being remembered during the «review» step of a PayPal Express checkout. (Thanks, Rafe Colton)
  • ENHANCEMENT/FIX: Search Filter would trigger incorrectly for REST API request by slug.
  • ENHANCEMENT/FIX: Didn’t always identify MasterCard cards correctly to set the CardType with some gateways.
  • ENHANCEMENT/FIX: Some custom code or add ons (e.g. the Prorating and Auto-renewal Checkbox add ons) would sometimes break PayPal Website Payments Pro and PayPal Express subscriptions by trying to set the «Profile Start Date» longer than 1 year out. We now limit the Profile Start Date to 1 year out and try to squeeze up to 1 additional year into a trial if it’s not already being used. This bug affects PayPal Standard as well, but the fix is different and not included in this release.
  • ENHANCEMENT: Tested up to WordPress 4.8.
  • ENHANCEMENT: Made countries translatable.
  • ENHANCEMENT: Improved performance via PHP $_SESSION management improvements. We now only open the session before we set session vars and close the session when we are finished with it.
  • ENHANCEMENT: Added to code to stop network activation of Paid Memberships Pro. (Thanks, Paul Barthmaier)

1.9.1 — 2017-05-11

  • BUG FIX: Fixed the code checking if the Stripe library is already loaded to compatability issues with other plugins bundling the Stripe API library.
  • BUG FIX: Cancel code now properly uses preg_replace when sanitizing the list of level ids to cancel.
  • FIX/ENHANCEMENT: Removed test/doc code from Stripe and Braintree libraries.
  • ENHANCEMENT: Now pausing the license nag for the first week of use and removed the «invalid» error if no key is being used.

1.9 — 2017-04-26

  • BUG: Fixed issue with cancelling 2Checkout recurring subscriptions. Now using the payment_transaction_id to find/cancel the sale’s recurring subscription since no subscription_transaction_id is being saved.
  • BUG: Fixed issue where old membership levels were not listed correctly in the cancellation email. (Thanks, Mike from Migrating Eye)
  • BUG: Fixed issue where «custom trial» values were not saving for discount codes.
  • BUG: Fixed issue where checkouts were still processing even if there were errors with the discount code used.
  • BUG: Fixed bug where settings added via the pmpro_custom_advanced_settings were not being saved to DB unless they were prefixed with custom_.
  • BUG: Fixed other formatting issues with settings added via pmpro_custom_advanced_settings.
  • BUG: Fixed issue where the sendInvoiceEmail method of the email class was expecting $order->discount_code to be a string, but it was sometimes a discount code object. (Thanks, Bill Stoltz)
  • FEATURE: Added the pmpro_member shortcode. See the Paid Memberships Pro website for documentation.
  • ENHANCEMENT: Added pmpro_account_membership_expiration_text filter to filter the expiration text that shows ona user’s membership account page.
  • ENHANCEMENT: Updated our Stripe and Braintree libraries to use their latest versions. This update allows our gateway integrations to support PHP7 and also removes support for PHP 5.2 and 5.3.
  • ENHANCEMENT: The Braintree level compatibility check now also looks for a properly named plan.
  • ENHANCEMENT: Better error handling when trying to update plugins that update against the PMPro license server.
  • ENHANCEMENT: Improved Italian translation. (Thanks, Francesco Pezzotti)
  • ENHANCEMENT: Improved German tranlsation. (Thanks, Simon)
  • ENHANCEMENT: Added a Sweedish tranlsation. (Thanks, Mathias Persson)
  • ENHANCEMENT: Added a «Chinese/Cantonese (Hong Kong SAR China)» tranlsation. (Thanks, Kai Chan)

1.8.13.6

  • BUG: Fixed bug where credit card expiration emails would be sent to users with PayPal Express orders.
  • BUG: Fixed bug when updating billing with Stripe.
  • BUG: Fixed bug where the archive/search filter was not running for logged out users.
  • ENHANCEMENT: Updated Finnish translations. (Thanks, JP Jakonen)
  • ENHANCEMENT: Added filter for modifying the order description in Stripe. (Thanks, Rafe Colton)

1.8.13.5

  • BUG: Fixed notifications.php to make sure it really only checks once per day. Also updated the URL checked to notifications.paidmembershipspro.com, which runs on its own server.

1.8.13.4

  • BUG/ENHANCEMENT: Changed the pmpro_button shortcode to pmpro_checkout_button. (The old pmpro_button will also still work. checkout_button works if you have Register Helper installed.)

1.8.13.3

  • BUG: Fixed bug when using a secondary gateway (e.g. PayPal Express) with Stripe as your primary gateway.

1.8.13.2

  • BUG: Fixed bug with updating credit cards through Braintree.
  • BUG: Fixed bug with updating credit cards through Stripe.
  • BUG: Fixed SQL warnings when generating the pmpro_membership_levelmeta table. (Thanks, itibet on GitHub)
  • BUG/ENHANCEMENT: Moved some update billing and checkout related code from the preheaders and page templates into the Braintree and Stripe classes.
  • ENHANCEMENT: Added pmpro_billing_order filter that functions similar to pmpro_checkout_order.
  • ENHANCEMENT: Added pmpro_billing_before_submit_button hook that functions similar to the pmpro_checkout_before_submit_button hook.
  • ENHANCEMENT: Clicking on a report widget no longer takes you to the details page. You have to click the details button. This allows us to add additional functionality to the widgets.
  • ENHANCEMENT: Updated reports widgets so the «details» button only shows if a page function is defined for that report. You can now have report widgets without details pages.
  • ENHANCEMENT: You can now click on a heading in the Membership Stats report widget to see data for up to 3 of your levels. The first 3 levels per the level ordering are shown.

1.8.13.1

  • BUG: Fixed issue where end dates were being set/saved incorrectly from the edit user/profile page in the dashboard.
  • BUG: Fixed warnings in the Braintree PHP library. (Thanks, Travis Shivers)
  • BUG: Fixed issue where the filtered $mypost object was not being used in the content filter if the post type was «page». (Thanks, James)
  • BUG: Removed the extra class=»input» attribute on the CVV field when the Stripe gateway is used. (Thanks, Rafe Colton)
  • BUG/ENHANCEMENT: Changed the number of X placeholders for masked credit cards to 12 (+ the last 4 stored) instead of 13. (Thanks, Rafe Colton)

1.8.13

  • FEATURE: The Stripe Webhook has been updated to process subscriptions cancelled from Stripe. PMPro will now cancel memberships for these users instead of sending an email to the admin.
  • BUG: Fixed various bugs in the PayPal IPN handler.
  • BUG: Fixed search on discount codes page in dashboard. (Thanks, Debjit Saha)
  • BUG: Fixed bug in Cancellations report where all-time cancellations were always 0.
  • BUG: Fixed link to payment settings on checkout notice. (Thanks, Coen Jacobs)
  • BUG: Timezone magic on edit user page in the dashboard to make sure the expiration date you select is the one set.
  • BUG: Swapped out deprecated uses of eregi_replace and split.
  • BUG/ENHANCEMENT: Now using add_query_arg in the pmpro_url() function. (Thanks, Debjit Saha)
  • ENHANCEMENT: Updating stylesheet for WordPress 4.7 and new Twenty Seventeen theme support.
  • ENHANCEMENT: Now longer warning of membership levels with cycle numbers > 1 when using the Payflow Pro gateway since Payflow now supports cycle numbers (frequencies) > 1.
  • ENHANCEMENT: Updated da_DK translation. (Thanks, bopdoq on GitHub)
  • ENHANCEMENT: Added pmpro_include_payment_option_for_paypal filter, which can be set to false to use PayPal WPP without the PayPal Express option.
  • ENHANCEMENT: Better dependency checking for Stripe and Braintree gateways.
  • ENHANCEMENT: Updated IPN handler and Stripe Webhook handler to use pmpro_cancelMembershipLevel instead of pmpro_changeMembershipLevele. This improves support for the MMPU addon.

1.8.12.1

  • BUG: Fixed bug when using the testing gateway.
  • BUG: Avoiding issues where is_user_logged in is not yet available for the pmpro_search_filter() function. (Thanks, d_enajetic)
  • ENHANCEMENT: Updated Italian translation. (Thanks again, Angelo)
  • ENHANCEMENT: You can now define(‘PMPRO_USE_SESSIONS’, false); in your wp-config.php to force PMPro to skip the call to session_start. Note that PayPal Express and some addons require sessions to function.

1.8.12

  • BUG: Fixed issue where «expiring soon» emails were sometimes sent more than needed.
  • BUG: Fixed issue where PayPal Standard IPN requests were being rejected if a tax amount was set in PayPal.
  • BUG: Fixed issue with Stripe subscription «updates» that were set to fire on «next payment», e.g. if you used Stripe with levels with a non-zero trial amount. When the update processed and created a new subscription, the old subscription was not being deleted and the new subscription ID was not being saved as a new order for future tracking purposes. If you use this feature, please check in Stripe to make sure your users don’t have extra subscriptions.
  • BUG: Fixed setting in PayPal/PayPal Express API calls from AUTOBILLAMT to AUTOBILLOUTAMT. This setting is set to AddToNextBilling, meaning that failed payment amounts are added to the next billing cycle’s amount if left unpaid. In most cases, a retry of the original billed amount goes through or the user’s subscription is cancelled. But just in case, this makes sure that outstanding balances are paid. (Thanks, jubstuff on GitHub)
  • BUG: Fixed warnings in the setGateway method of the MemberOrder class for cases where the gateway is missing or the class file is not found.
  • BUG/ENHANCEMENT: Moved the pmpro_before_change_membership_level hook to fire a little bit earlier to make it easier to determine the old level status/end date/etc before it gets updated. (Thanks, MrVibe on GitHub)
  • ENHANCEMENT: Replaced the Force SSL option with an explanation if the entire site is over HTTPS. We are already ignoring the option in these cases.

1.8.11.2

  • BUG: Fixed a bug introduced in 1.8.11 that kept PMPro from tracking coupon code uses. Any checkout with a discount code while running 1.8.11 won’t have properly tracked the discount code use. You may want to adjust your «uses» numbers for your codes, and hand check any reporting/etc that relied on discount codes. Users of the Sponsored Members addon will have been affected too. Discount codes will need to be made manually for any sponsor who checked out.
  • BUG: Fix to the expiration warnings code. Making sure it finds all members who are expiring soon while also keeping track of when emails are sent so users don’t get too many emails.
  • BUG: Fixed issue where pmpro_before_change_membership_level was running after levels had been changed.
  • BUG: Fixed some warnings.
  • ENHANCEMENT: Updated Italian translations. (Thanks, Angelo)

1.8.11.1

  • BUG: Fixed issue introduced in 1.8.11 where the pmpro_default_level custom field was being ignored at checkout.
  • BUG: Fixed bugs in DB calls made for the compatibility checks for various gateways.
  • BUG: Now sending a FREQUENCY parameter for PayPal Payflow orders.

1.8.11

  • BUG: Fixed URL used when checking for addon updates.
  • BUG: Now enqueueing the jquery.creditCardValidator.js file in Billing preheader.
  • BUG: Fixed issues where PayPal IPN updates would sometimes log $0 instead of the actual billing amount.
  • BUG: Fixed warnings in the PayPal IPN handler.
  • BUG/ENHANCEMENT: Added pmpro_checkout_level filter and now using that filter to apply the_content filters to the level description at checkout. This allows you to turn off the the_content filters (e.g. processing shortcodes) by using remove_filter(‘pmpro_checkout_level’, ‘pmpro_pmpro_checkout_level’); in a custom plugin.
  • BUG/ENHANCEMENT: Using the pmpro_confirmation_message filter on the confirmation page whether there is an invoice or not. Now also adding the the_content filters to the confirmation message. You can disable this by using remove_filter(‘pmpro_confirmation_message’, ‘pmpro_pmpro_confirmation_message’); in a custom plugin.
  • ENHANCEMENT: Now tracking IPN event ids in order notes for recurring orders.
  • ENHANCEMENT: Added pmpro_subscription_ipn_event_processed hook to IPN handler.
  • ENHANCEMENT: Added pmpro_set_message filter to edit PMPro error messages. Passes the message and type.
  • ENHANCEMENT: Now listing categories in hierarchical format in the Content Settings section of Membership Levels.
  • ENHANCEMENT: Added pmpro_areLevelsFree() function to check if all levels in an array of levels are free.
  • ENHANCEMENT: Added pmpro_getLevelsCost() — with an s — function to get the combined cost of multiple levels in an array.
  • ENHANCEMENT: Added pmpro_getLevelsExpiration() — with an s — function to get the combined expiration text for multiple levels in array.
  • ENHANCEMENT: Created the pmpro_getLevelAtCheckout function that modularizes some of the logic of creating the pmpro_level global at checkout.
  • ENHANCEMENT: Added pmpro_members_list_user filter used on the admin members list and members list CSV export.
  • ENHANCEMENT: Added a 4th parameter $cancel_level to pmpro_changeMembershipLevel(). If set, that level will definitely be cancelled locally and at the gateway. This parameter is also passed to the pmpro_before_change_membership_level and pmpro_after_change_membership_level hook.
  • ENHANCEMENT: Added a new function pmpro_cancelMembershipLevel($level_id, $user_id, $old_level_status) that acts as a wrapper to pass the $cancel_level param to pmpro_changeMembershipLevel().
  • ENHANCEMENT: Updated the cancel page on the frontend to support the Multiple Memberships per User addon. All memberships are shown. You can cancel individual memberships separately. The language of the confirm button mentions memberships vs account.
  • ENHANCEMENT: Added pmpro_getMemberOrdersByCheckoutID($checkout_id) function to support Multiple Memberships per User and others using the checkout_id.
  • ENHANCEMENT: Added a refund($order, $transaction_id) method to the PMPro_stripe class. This will be used by the Multiple Memberships per User addon and eventually used in other areas by the core pluginn.

View All Members

Provided that you have the appropriate permissions, you will be able to see the Members entry on the or in the . Clicking one of these links will bring you to the View all Members page, the default page for the Members List section. There is also a page in this section, where you can search for members registered on the forum.

On the View All Members page, you will see the list of all the members registered on the forum. Pages are used so that there are not too many members listed on one single page. When there is more than one page, the additional pages can be selected from here. On the right side of the "Members List" title bar, every letter of the English alphabet is displayed. These letters are used to jump to the usernames of registered members that begin with that letter, so that you do not have to scroll through several pages to find them. This does not filter out all of the usernames beginning with different letters, but rather serves as an anchor, so you will be directed to usernames that start with the selected letter.

All usernames in the memberlist can be ordered by: Status (Online/Offline), Username, Email, Website, ICQ, AIM, YIM, MSN, Position, Date Registered, and Posts. These column headings are links that can be used to sort the list in ascending or descending order, or to reverse the sort order of the column under the heading that is currently used to sort the list.

Search for Members

This section allows you to do either a simple search for members, or to choose to filter your results by using additional parameters. You can search for members based on their username, email address, messenger nickname, website, or position.

The search results will show matches for the terms that you enter in the search field. If any of the additional search parameters are selected, then the results will also be filtered accordingly. The search does not look only for full-word exact matches, but also for any parts of text that match the search terms. For this reason, if the search term represents only part of the word that you are looking for, then the results may show many more matches than expected.

Some of the additional search parameters relate to information that users can either choose not to include in their profile (messenger nickname, website) or they can choose not to reveal it to the public (email), so using these parameters might not always bring up the results that you are looking for. The results of the search will be more accurate the more letters/words that are used in the search.