Уверен, что каждый из разработчиков плагинов и тем для WordPress хоть раз, но задумывался над вопросом монетизации своих проектов. Единственный нюанс, который стоял на пути создания платных версий - это система обновления. У WordPress есть свой сервис - один для всех. Это очень не удобно, если вы пишите платную версию своего продукта, поскольку разделить код не получится со стандартным хранилищем обновлений. Да и выкладывать открытый код с каким-либо флажком вида платная или бесплатная версия - это точно не выход. В итоге все приходят либо к использованию уже готовых но платных сервисов, либо к созданию своей собственной системы обновления. К великому счастью, некоторые умные люди (да прибудет с ними сила) уже создали подобное детище. Я собираюсь поделиться опытом на эту тему.
Итак, у меня есть плагин, который я бы хотел обновлять через свой сервис. Допустим, у нас есть доменное имя вида http://update.mysite.com/api, к которому мы можем обратиться и спросить версию плагина и другие его подробности.
Исходный PHP код API функций можно скачать здесь. Скачиваем, распаковываем на сервер. В папке API есть три файла:
Для сервиса обновления все готово. Главное, не забудьте положить архив с новой версией плагина по указанному пути.
Теперь осталась реализация.
Со стороны программирования - все. Проверял на реальном проекте - все работает.
Если статья была полезной, нажмите на рекламку в блоге.
Итак, у меня есть плагин, который я бы хотел обновлять через свой сервис. Допустим, у нас есть доменное имя вида http://update.mysite.com/api, к которому мы можем обратиться и спросить версию плагина и другие его подробности.
Создание сервиса обновлений
Для того, что бы сервис работал нужно совсем немного и, как я уже говорил, есть умные люди, которые уже сделали подобную систему.Исходный PHP код API функций можно скачать здесь. Скачиваем, распаковываем на сервер. В папке API есть три файла:
- download.php
- index.php
- packages.php
// Plugin with update info $packages['ls_spam'] = array( //Replace plugin with the plugin slug that updates will be checking for 'versions' => array( '0.0.6' => array( //Array name should be set to current version of update 'version' => '0.0.6', //Current version available 'date' => '2014-10-11', //Date version was released 'author' => '<a href="htp://mysite.ru">Aleksey Komov</a>', //Author name - can be linked using html - <a href="http://link-to-site.com">Author Name</a> 'requires' => '2.8', // WP version required for plugin 'tested' => '4.0.0', // WP version tested with 'homepage' => 'http://your_plugin_website', // Site devoted to your plugin if available 'downloaded' => '1000', // Number of times downloaded 'external' => '', // Unused //plugin.zip is the same as file_name 'package' => 'http://updates.mysite.com/api/download.php?key=' . md5('ls_spam.zip' . mktime(0,0,0,date("m"),date("d"),date("Y"))), // 'package' => 'http://updates.mysite.com/api/update/ls_spam.zip', //file_name is the name of the file in the update folder. 'file_name' => 'ls_spam.zip', 'sections' => array( /* Plugin Info sections tabs. Each key will be used as the title of the tab, value is the contents of tab. Must be lowercase to function properly HTML can be used in all sections below for formating. Must be properly escaped ie a single quote would have to be \' Screenshot section must use exteranl links for img tags. */ 'description' => 'E-Mail service.', //Description Tab 'installation' => 'Install Info', //Installaion Tab 'screenshots' => 'Screen Shots', //Screen Shots 'changelog' => '' . 'Version 0.0.6<br />' . '* Price order correction' . '* CSS correction' . 'Version 0.0.5<br />' . '* Added autoupdate check<br />' . '', //Change Log Tab 'faq' => 'FAQ', //FAQ Tab 'other notes' => 'Other Notes' //Other Notes Tab ) ) ), 'info' => array( 'url' => 'http://your_plugin_webiste' // Site devoted to your plugin if available ) );
Для сервиса обновления все готово. Главное, не забудьте положить архив с новой версией плагина по указанному пути.
Автопроверка обновлений
Осталась самая малость - заставить WordPress проверять обновления не только на своем сервисе, но и на нашем. Конечно, лезть в движок и править код совсем не нужно. Можно пожертвовать глобализацией и сделать это через хуки, их всего 2:- pre_set_site_transient_update_plugins - для проверки обновлений
- plugins_api - для процесса обновления
/* Автообновления */ add_filter('pre_set_site_transient_update_plugins', array($this, 'CheckForUpdate')); add_filter('plugins_api', array($this, 'CallPluginApi'), 10, 3);
Теперь осталась реализация.
// Push in plugin version information to get the update notification public function CheckForUpdate($transient) { if(empty($transient->checked)) { return $transient; } $args = array( 'slug' => $this->pluginSlug, 'version' => $transient->checked[$this->pluginSlug . '/index.php'], ); $request_string = array( 'body' => array( 'action' => 'basic_check', 'request' => serialize($args), 'api-key' => md5(get_bloginfo('url')) ), 'user-agent' => 'WordPress/' . $this->wpVersion . '; ' . get_bloginfo('url') ); // Start checking for an update $raw_response = wp_remote_post($this->apiUrl, $request_string); if(!is_wp_error($raw_response) && ($raw_response['response']['code'] == 200)) { $response = unserialize($raw_response['body']); } if(is_object($response) && !empty($response)) { // Feed the update data into WP updater $transient->response[$this->pluginSlug . '/index.php'] = $response; } return $transient; } // Push in plugin version information to display in the details lightbox public function CallPluginApi($def, $action, $args) { if(!isset($args->slug) || ($args->slug != $this->pluginSlug)) return false; // Get the current version $plugin_info = get_site_transient('update_plugins'); $current_version = $plugin_info->checked[$this->pluginSlug . '/index.php']; $args->version = $current_version; $request_string = array( 'body' => array( 'action' => $action, 'request' => serialize($args), 'api-key' => md5(get_bloginfo('url')) ), 'blocking' => true, 'user-agent' => 'WordPress/' . $this->wpVersion . '; ' . get_bloginfo('url') ); $request = wp_remote_post($this->apiUrl, $request_string); if(is_wp_error($request)) { $res = new WP_Error('plugins_api_failed', __('An Unexpected HTTP Error occurred during the API request.</p> <p><a href="?" onclick="document.location.reload(); return false;">Try again</a>', 'lswp'), $request->get_error_message()); } else { $res = unserialize($request['body']); if($res === false) $res = new WP_Error('plugins_api_failed', __('An unknown error occurred', 'lswp'), $request['body']); } return $res; }
Со стороны программирования - все. Проверял на реальном проекте - все работает.
Нюансы при обновлении
Главный совет - перед первым авто обновлением сделайте копию плагина на всякий случай. Собственно, что за случай может произойти? Я столкнулся с таким случаем еще на этапе разработки. WordPress скачивал и распаковывал архив с обновлением, потом затирал текущую версию и выдавал ошибку типа "Не удалось удалить предыдущую версию плагина". Парадокс был в том, что он удалял все кроме самой папки. Причина крылась в правах доступа к папке - у WordPress должен быть полный доступ к этой папке. Когда все перенес на внешний сервер такой проблемы не возникало.Если статья была полезной, нажмите на рекламку в блоге.
Комментарии
Отправить комментарий