Compare commits

...

21 commits

Author SHA1 Message Date
Julien Liabeuf
8c3a084e10
Merge pull request #6 from mallardduck/patch-1
Fix comparison within is_time() method
2018-11-20 19:56:19 +07:00
Dan
c9bae4c60f
Update review.php 2018-11-16 17:49:38 -05:00
Julien Liabeuf
8df8feafa4
Merge pull request #11 from Mte90/patch-1
Improve composer loading
2018-08-15 08:34:30 +07:00
Daniele Scasciafratte
a9efc4fb2d
Update review.php 2018-08-13 22:10:27 +02:00
Dan
a47a0fc6fa Fix comparison within is_time() method
Using false here is causing the check to ALWAYS evaluate as false since the value is being cast to an int. A check of `bool === int` can never be true, so updating this to comparing for 0 is the best solution.
2017-04-09 17:34:56 -04:00
Julien Liabeuf
cb43e768e0 Bump version number again. Actually forgot to do it when releasing 2.0. 2016-09-27 11:04:50 +07:00
Julien Liabeuf
0f616f7edd Update review URLs - fixes #4 2016-09-27 11:02:43 +07:00
Julien Liabeuf
973892a9a0 Bump version number 2016-09-27 11:02:12 +07:00
Julien Liabeuf
4f9d9633a1 Fix calculation error 2016-09-27 11:01:36 +07:00
Julien Liabeuf
66baf1dbd9 Typecast var 2016-09-27 11:01:06 +07:00
Julien Liabeuf
1e24fa8a8f Update image src 2016-07-03 21:31:46 +07:00
Julien Liabeuf
686edccb6e Merge branch 'develop' of github.com:julien731/WP-Review-Me into develop 2016-04-20 19:38:24 +07:00
Julien Liabeuf
f55e83a0e5 Add info note about dropping integrations 2016-04-20 19:37:05 +07:00
Julien Liabeuf
e7ea9ad376 Update instructions in readme.md 2016-04-20 19:37:05 +07:00
Julien Liabeuf
9930e7085b Remove integrations - closes #3 closes #2 2016-04-20 19:37:05 +07:00
Julien Liabeuf
1f454a7629 Track the develop branch on Scrutinizer 2016-04-20 19:37:05 +07:00
Julien Liabeuf
25598778fc Finish integrationless 2016-04-20 19:35:44 +07:00
Julien Liabeuf
db6090587d Add info note about dropping integrations 2016-04-20 19:35:18 +07:00
Julien Liabeuf
ca9d11a379 Update instructions in readme.md 2016-04-20 08:39:28 +07:00
Julien Liabeuf
5688afde4e Remove integrations - closes #3 closes #2 2016-04-20 08:37:23 +07:00
Julien Liabeuf
73c551ebe6 Track the develop branch on Scrutinizer 2016-04-19 01:01:37 +07:00
5 changed files with 26 additions and 624 deletions

View file

@ -1,6 +1,8 @@
# WP Review Me

[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/julien731/WP-Review-Me/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/julien731/WP-Review-Me/?branch=master)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/julien731/WP-Review-Me/badges/quality-score.png?b=develop)](https://scrutinizer-ci.com/g/julien731/WP-Review-Me/?branch=develop)

*In order to comply with the WordPress.org guidelines, the EDD integration has been removed and the WooCommerce integration has been dropped.*

Are you distributing WordPress themes or plugins on WordPress.org? Then you know how important reviews are.

@ -8,7 +10,7 @@ The bad thing with reviews is that, while unhappy users love to let the world kn

How can you get more good reviews? Simply ask your users.

![WP Review Me](http://i.imgur.com/iZk4Bgu.png)
![WP Review Me](http://i.imgur.com/9oNGvm2.png)

## How It Works

@ -31,17 +33,9 @@ composer require julien731/wp-review-me
Creating a new review prompt would look like that:

```
new WRM_WordPress( array( 'days_after' => 10, 'type' => 'plugin', 'slug' => 'my-plugin' ) );
new WP_Review_Me( array( 'days_after' => 10, 'type' => 'plugin', 'slug' => 'my-plugin' ) );
```

This is the simplest way of creating a review prompt. If you want to customize it further, a few advanced parameters are available.

You can see the documentation on the wiki page: https://github.com/julien731/WP-Review-Me/wiki

## Integrations

Because users sometimes won't take the time to leave a review without an incentive, there are a couple of integrations made just for that.

### Easy Digital Downloads

With the EDD integration, you can automatically generate a discount code for the user in exchange for a review. See the [documentation for the EDD integration](https://github.com/julien731/WP-Review-Me/wiki/Integration:-EDD).

View file

@ -1,243 +0,0 @@
<?php
/**
* WP Review Me
*
* @package WP Review Me/Integrations
* @author Julien Liabeuf <julien@liabeuf.fr>
* @version 1.0
* @license GPL-2.0+
* @link https://julienliabeuf.com
* @copyright 2016 Julien Liabeuf
*/

// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}

class WRM_EDD extends WP_Review_Me {

/**
* URL of the EDD shop
*
* @since 1.0
* @var string
*/
protected $edd_url;

/**
* The discount code settings
*
* @since 1.0
* @var array
*/
protected $discount;

/**
* The discount code generated
*
* @since 1.0
* @var string
*/
protected $code;

/**
* The confirmation e-mail data
*
* @since 1.0
* @var array
*/
protected $email;

public function __construct( $args, $email = array() ) {

$this->edd_url = isset( $args['edd_url'] ) ? esc_url( $args['edd_url'] ) : '';
$this->discount = isset( $args['edd_discount'] ) && is_array( $args['edd_discount'] ) ? wp_parse_args( $args['edd_discount'], $this->discount_defaults() ) : $this->discount_defaults();
$this->email = $email;

// Call parent constructor
parent::__construct( $args );

// Register our discount action
add_action( 'wrm_after_notice_dismissed', array( $this, 'query_discount_ajax' ), 10, 2 );

}

/**
* Get the EDD discount default options
*
* @since 1.0
* @return array
*/
private function discount_defaults() {

$defaults = array(
'type' => 'percentage',
'amount' => 20,
'validity' => 30, // In days
);

return $defaults;

}

/**
* Trigger the EDD discount query via Ajax
*
* @since 1.0
*
* @param string $link_id Unique ID of the link clicked to generate the discount
*
* @return void
*/
public function query_discount_ajax( $link_id ) {

// Not this notice. Abort.
if ( $link_id !== $this->link_id ) {
echo 'not this instance job';

return;
}

echo $this->query_discount();

}

/**
* Send the HTTP query to the EDD shop
*
* @since 1.0
* @return string|true
*/
protected function query_discount() {

$endpoint = esc_url( add_query_arg( 'wrm_action', 'discount', $this->edd_url ) );
$data = array( 'wrm_email' => get_bloginfo( 'admin_email' ), 'wrm_discount' => $this->discount ); // Wrap our vars to avoid post names issues

$response = wp_remote_post( $endpoint, array(
'method' => 'POST',
'timeout' => 20,
'redirection' => 5,
'httpversion' => '1.1',
'blocking' => true,
'body' => $data,
'user-agent' => 'WRM/' . $this->version . '; ' . get_bloginfo( 'url' )
) );

if ( is_wp_error( $response ) ) {
return $response->get_error_message();
}

if ( 200 != wp_remote_retrieve_response_code( $response ) ) {
return wp_remote_retrieve_response_message( $response );
}

$body = json_decode( wp_remote_retrieve_body( $response ) );

if ( false === $body ) {
return __( 'Unknown error', 'wp-review-me' );
}

if ( 'success' === $body->result ) {
$this->code = trim( $body->message );
$this->email_code();
return $this->code;
}

return $body->message;

}

/**
* Get the e-mail data
*
* @since 1.0
* @return array
*/
protected function get_email_data() {

$body = '<p>Hi,</p><p>From our entire team, many thanks for your review.</p><p>While you just spent a few minutes writing it, your testimonial will be a big help to us.</p><p>Many users don\'t realize it but reviews are a key part of the promotion work for our product. This allows us to increase our user base, and thus get more support for improving our product.</p><p>As a thank you from us, please find hereafter your discount code for a {{amount}} discount valid until {{expiration}}:</p><p>Your discount code: <strong>{{code}}</strong></p><p>Enjoy the product!</p>';

if ( isset( $this->email['body'] ) ) {
$body = $this->email['body'];
}

$tags = array( 'code', 'amount', 'expiration' );

foreach ( $tags as $tag ) {

$find = '{{' . $tag . '}}';

switch ( $tag ) {

case 'code':
$body = str_replace( $find, $this->code, $body );
break;

case 'amount':

$amount = $this->discount['amount'];

if ( 'percentage' === $this->discount['type'] ) {
$amount = $amount . '%';
}

$body = str_replace( $find, $amount, $body );
break;

case 'expiration':
$expiration = date( get_option( 'date_format' ), time() + ( (int) $this->discount['validity'] * 86400 ) );
$body = str_replace( $find, $expiration, $body );
break;

}

}

$email['body'] = $body;
$email['subject'] = isset( $this->email['subject'] ) ? sanitize_text_field( $this->email['subject'] ) : esc_html__( 'Your discount code', 'wp-review-me' );
$email['from_name'] = isset( $this->email['from_name'] ) ? sanitize_text_field( $this->email['from_name'] ) : get_bloginfo( 'name' );
$email['from_email'] = isset( $this->email['from_email'] ) ? sanitize_text_field( $this->email['from_email'] ) : get_bloginfo( 'admin_email' );

return apply_filters( 'wrm_edd_email', $email );

}

/**
* E-mail the discount code to the reviewer
*
* @since 1.0
* @return bool
*/
protected function email_code() {

$email = $this->get_email_data();
$from_name = $email['from_name'];
$from_email = $email['from_email'];
$headers = array(
"MIME-Version: 1.0",
"Content-type: text/html; charset=utf-8",
"From: $from_name <$from_email>",
);

return wp_mail( get_bloginfo( 'admin_email' ), $email['subject'], $email['body'], $headers );

}

/**
* Get the review prompt message
*
* @since 1.0
* @return string
*/
protected function get_message() {

$message = $this->message;
$link = $this->get_review_link_tag();
$message = $message . ' ' . $link;

return wp_kses_post( $message );

}

}

View file

@ -1,47 +0,0 @@
<?php
/**
* WP Review Me
*
* @package WP Review Me/Integrations
* @author Julien Liabeuf <julien@liabeuf.fr>
* @version 1.0
* @license GPL-2.0+
* @link https://julienliabeuf.com
* @copyright 2016 Julien Liabeuf
*/

// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}

class WRM_WordPress extends WP_Review_Me {

/**
* WRM_WordPress constructor
*
* @since 1.0
*
* @param array $args
*/
public function __construct( $args ) {
parent::__construct( $args );
}

/**
* Get the review prompt message
*
* @since 1.0
* @return string
*/
protected function get_message() {

$message = $this->message;
$link = $this->get_review_link_tag();
$message = $message . ' ' . $link;

return wp_kses_post( $message );

}

}

View file

@ -13,20 +13,15 @@
*
* @package WP Review Me
* @author Julien Liabeuf <julien@liabeuf.fr>
* @version 1.0
* @version 2.0.1
* @license GPL-2.0+
* @link https://julienliabeuf.com
* @copyright 2016 Julien Liabeuf
*/

// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}

if ( ! class_exists( 'WP_Review_Me' ) ) {

abstract class WP_Review_Me {
class WP_Review_Me {

/**
* Library version
@ -34,7 +29,7 @@ if ( ! class_exists( 'WP_Review_Me' ) ) {
* @since 1.0
* @var string
*/
public $version = '1.0';
public $version = '2.0.1';

/**
* Required version of PHP.
@ -238,14 +233,14 @@ if ( ! class_exists( 'WP_Review_Me' ) ) {
*/
public function is_time() {

$installed = get_option( $this->key, false );
$installed = (int) get_option( $this->key, 0 );

if ( false === $installed ) {
if ( 0 === $installed ) {
$this->setup_date();
$installed = time();
}

if ( $installed + ( $this->days + 86400 ) > time() ) {
if ( $installed + ( $this->days * 86400 ) > time() ) {
return false;
}

@ -271,23 +266,23 @@ if ( ! class_exists( 'WP_Review_Me' ) ) {
*/
protected function get_review_link() {

$link = 'https://wordpress.org/support/view/';
$link = 'https://wordpress.org/support/';

switch ( $this->type ) {

case 'theme':
$link .= 'theme-reviews/';
$link .= 'theme/';
break;

case 'plugin':
$link .= 'plugin-reviews/';
$link .= 'plugin/';
break;

}

$link .= $this->slug;
$link .= $this->slug . '/reviews';
$link = add_query_arg( 'rate', $this->rating, $link );
$link = esc_url( $link . '#postform' );
$link = esc_url( $link . '#new-post' );

return $link;

@ -411,12 +406,16 @@ if ( ! class_exists( 'WP_Review_Me' ) ) {
* @since 1.0
* @return string
*/
abstract protected function get_message();
protected function get_message() {

$message = $this->message;
$link = $this->get_review_link_tag();
$message = $message . ' ' . $link;

return wp_kses_post( $message );

}

}

// Load integrations
require_once( dirname( __FILE__ ) . '/includes/integrations/class-wordpress.php' );
require_once( dirname( __FILE__ ) . '/includes/integrations/class-edd.php' );

}
}

View file

@ -1,301 +0,0 @@
<?php
/**
* WP Review Me EDD Bridge
*
* This bridge plugin handles the discount creation triggered by WP Review Me
*
* LICENSE: 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 3 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, see <http://opensource.org/licenses/gpl-license.php>
*
* @package WP Review Me EDD Bridge
* @author Julien Liabeuf <julien@liabeuf.fr>
* @version 1.0
* @license GPL-2.0+
* @link https://julienliabeuf.com
* @copyright 2016 Julien Liabeuf
*
* Plugin Name: WP Review Me EDD Bridge
* Plugin URI: https://github.com/julien731/WP-Review-Me
* Description: Handles POST requests from a WP Review Me client
* Author: Julien Liabeuf
* Author URI: https://julienliabeuf.com
* Version: 1.0
* Text Domain: wp-review-me
* Domain Path: languages
*/

// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}

if ( ! class_exists( 'WRM_EDD_Bridge' ) ):

/**
* Main WRM EDD class
*
* This class is the one and only instance of the plugin. It is used
* to load the core and all its components.
*
* @since 3.2.5
*/
final class WRM_EDD_Bridge {

/**
* Minimum version of WordPress required ot run the plugin
*
* @since 1.0
* @var string
*/
public $wordpress_version_required = '3.8';

/**
* Required version of PHP.
*
* Follow WordPress latest requirements and require
* PHP version 5.2 at least.
*
* @since 1.0
* @var string
*/
public $php_version_required = '5.2';

/**
* Email of the user
*
* @since 1.0
* @var string
*/
protected $email;

/**
* Discount code
*
* @since 1.0
* @var string
*/
protected $code;

/**
* Throw error on object clone
*
* The whole idea of the singleton design pattern is that there is a single
* object therefore, we don't want the object to be cloned.
*
* @since 3.2.5
* @return void
*/
public function __clone() {
// Cloning instances of the class is forbidden
_doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'awesome-support' ), '3.2.5' );
}

/**
* Disable unserializing of the class
*
* @since 3.2.5
* @return void
*/
public function __wakeup() {
// Unserializing instances of the class is forbidden
_doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'awesome-support' ), '3.2.5' );
}

public function __construct() {
add_action( 'init', array( $this, 'init' ) );
}

/**
* Initialize the bridge
*
* @since 1.0
* @return bool|void
*/
public function init() {

// Some work to do?
if ( ! empty( $_GET ) && isset( $_GET['wrm_action'] ) ) {

switch ( $_GET['wrm_action'] ) {

case 'discount':
$this->discount();
break;
}

}

}

/**
* Run some checks and generate the discount if it's all good
*
* @since 1.0
* @return void
*/
protected function discount() {

$result = array( 'result' => 'error' );

// Make sure the WordPress version is recent enough
if ( ! $this->is_version_compatible() ) {
$result['message'] = 'WordPress version incompatible';
echo json_encode( $result );
die();
}

// Make sure we have a version of PHP that's not too old
if ( ! $this->is_php_version_enough() ) {
$result['message'] = 'PHP version incompatible';
echo json_encode( $result );
die();
}

// Check if EDD is here
if ( ! function_exists( 'edd_store_discount' ) ) {
$result['message'] = 'EDD not active';
echo json_encode( $result );
die();
}

// Make sure we have an e-mail
if ( ! isset( $_POST['wrm_email'] ) ) {
$result['message'] = 'Email missing';
echo json_encode( $result );
die();
}

$this->email = $_POST['wrm_email'];
$this->code = md5( $this->email );

if ( ! $this->is_code_unique() ) {
$result['message'] = 'Code already claimed';
echo json_encode( $result );
die();
}

$message = $this->insert_discount();
$result['result'] = $message ? 'success' : 'error';
$result['message'] = $message ? $this->code : 'unknown error';

echo json_encode( $result );
die();

}

/**
* Check if the core version is compatible with this.
*
* @since 3.3
* @return boolean
*/
private function is_version_compatible() {

if ( empty( $this->wordpress_version_required ) ) {
return true;
}

if ( version_compare( get_bloginfo( 'version' ), $this->wordpress_version_required, '<' ) ) {
return false;
}

return true;

}

/**
* Check if the version of PHP is compatible with this addon.
*
* @since 3.3
* @return boolean
*/
private function is_php_version_enough() {

/**
* No version set, we assume everything is fine.
*/
if ( empty( $this->php_version_required ) ) {
return true;
}

if ( version_compare( phpversion(), $this->php_version_required, '<' ) ) {
return false;
}

return true;

}

protected function is_code_unique() {
return ! is_null( $this->code ) && edd_get_discount_by_code( $this->code ) ? false : true;
}

/**
* Get the EDD discount default options
*
* @since 1.0
* @return array
*/
private function discount_defaults() {

$defaults = array(
'type' => 'percentage',
'amount' => 20,
'validity' => 30, // In days
);

return $defaults;

}

/**
* Insert the discount code.
*
* @since 0.1.0
* @return integer Discount ID
*/
protected function insert_discount() {

$discount = isset( $_POST['wrm_discount'] ) ? wp_parse_args( $_POST['wrm_discount'], $this->discount_defaults() ) : $this->discount_defaults();

// Make sure the discount type exists
if ( ! in_array( $discount['type'], array( 'percent', 'flat' ) ) ) {
$discount['type'] = 'percent';
}

// Make sure the discount is not over 100% (for percentage discounts)
if ( 'percent' === $discount['type'] && (int) $discount['amount'] > 100 ) {
$discount['amount'] = 100;
}

$details = array(
'code' => $this->code,
'name' => sprintf( 'Discount for a review %s', $this->email ),
'status' => 'active',
'uses' => 0,
'max' => 1,
'amount' => $discount['amount'],
'start' => date( 'Y-m-d' ),
'expiration' => date( 'Y-m-d', strtotime( date( 'Y-m-d' ) . "+ {$discount['validity']} days" ) ),
'type' => $discount['type'],
'min_price' => 0,
'products' => array(),
'product_condition' => 'any',
'excluded_products' => array(),
'not_global' => true,
'use_once' => true,
);

return edd_store_discount( $details );

}

}

endif;

new WRM_EDD_Bridge();