WP Users list
- migration for filters & segment_filter tables - models for new tables - update of Listing JSX to allow for conditional display of item actions
This commit is contained in:
@ -79,6 +79,12 @@ define(
|
|||||||
|
|
||||||
if(custom_actions.length > 0) {
|
if(custom_actions.length > 0) {
|
||||||
item_actions = custom_actions.map(function(action, index) {
|
item_actions = custom_actions.map(function(action, index) {
|
||||||
|
if(action.onFilter !== undefined) {
|
||||||
|
if(action.onFilter(this.props.item) === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(action.refresh) {
|
if(action.refresh) {
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
@ -121,6 +127,12 @@ define(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var is_readonly = (
|
||||||
|
(this.props.onFilterItem !== undefined)
|
||||||
|
? this.props.onFilterItem(this.props.item)
|
||||||
|
: false
|
||||||
|
);
|
||||||
|
|
||||||
if(this.props.group === 'trash') {
|
if(this.props.group === 'trash') {
|
||||||
var actions = (
|
var actions = (
|
||||||
<div>
|
<div>
|
||||||
@ -158,17 +170,19 @@ define(
|
|||||||
<div>
|
<div>
|
||||||
<div className="row-actions">
|
<div className="row-actions">
|
||||||
{ item_actions }
|
{ item_actions }
|
||||||
{ ' | ' }
|
{ (is_readonly) ? '' : (
|
||||||
<span className="trash">
|
<span className="trash">
|
||||||
<a
|
{ ' | ' }
|
||||||
href="javascript:;"
|
<a
|
||||||
onClick={ this.handleTrashItem.bind(
|
href="javascript:;"
|
||||||
null,
|
onClick={ this.handleTrashItem.bind(
|
||||||
this.props.item.id
|
null,
|
||||||
) }>
|
this.props.item.id
|
||||||
Trash
|
) }>
|
||||||
</a>
|
Trash
|
||||||
</span>
|
</a>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={ this.handleToggleItem.bind(null, this.props.item.id) }
|
onClick={ this.handleToggleItem.bind(null, this.props.item.id) }
|
||||||
@ -258,6 +272,7 @@ define(
|
|||||||
columns={ this.props.columns }
|
columns={ this.props.columns }
|
||||||
onSelectItem={ this.props.onSelectItem }
|
onSelectItem={ this.props.onSelectItem }
|
||||||
onRenderItem={ this.props.onRenderItem }
|
onRenderItem={ this.props.onRenderItem }
|
||||||
|
onFilterItem={ this.props.onFilterItem }
|
||||||
onDeleteItem={ this.props.onDeleteItem }
|
onDeleteItem={ this.props.onDeleteItem }
|
||||||
onRestoreItem={ this.props.onRestoreItem }
|
onRestoreItem={ this.props.onRestoreItem }
|
||||||
onTrashItem={ this.props.onTrashItem }
|
onTrashItem={ this.props.onTrashItem }
|
||||||
@ -721,6 +736,7 @@ define(
|
|||||||
|
|
||||||
<ListingItems
|
<ListingItems
|
||||||
onRenderItem={ this.handleRenderItem }
|
onRenderItem={ this.handleRenderItem }
|
||||||
|
onFilterItem={ this.props.onFilterItem }
|
||||||
onDeleteItem={ this.handleDeleteItem }
|
onDeleteItem={ this.handleDeleteItem }
|
||||||
onRestoreItem={ this.handleRestoreItem }
|
onRestoreItem={ this.handleRestoreItem }
|
||||||
onTrashItem={ this.handleTrashItem }
|
onTrashItem={ this.handleTrashItem }
|
||||||
|
@ -121,6 +121,20 @@ const item_actions = [
|
|||||||
);
|
);
|
||||||
refresh();
|
refresh();
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
onFilter: function(segment) {
|
||||||
|
return (segment.filters.length === 0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'sync_segment',
|
||||||
|
label: 'Update',
|
||||||
|
className: 'update',
|
||||||
|
onClick: function(item, refresh) {
|
||||||
|
console.log(item);
|
||||||
|
},
|
||||||
|
onFilter: function(segment) {
|
||||||
|
return (segment.filters.length > 0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -142,13 +156,15 @@ const bulk_actions = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const SegmentList = React.createClass({
|
const SegmentList = React.createClass({
|
||||||
|
filterItem: function(segment) {
|
||||||
|
return !!(segment.filters.length > 0);
|
||||||
|
},
|
||||||
renderItem: function(segment, actions) {
|
renderItem: function(segment, actions) {
|
||||||
var rowClasses = classNames(
|
var rowClasses = classNames(
|
||||||
'manage-column',
|
'manage-column',
|
||||||
'column-primary',
|
'column-primary',
|
||||||
'has-row-actions'
|
'has-row-actions'
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<td className={ rowClasses }>
|
<td className={ rowClasses }>
|
||||||
@ -190,6 +206,7 @@ const SegmentList = React.createClass({
|
|||||||
limit={ 1000 }
|
limit={ 1000 }
|
||||||
endpoint="segments"
|
endpoint="segments"
|
||||||
onRenderItem={ this.renderItem }
|
onRenderItem={ this.renderItem }
|
||||||
|
onFilterItem={ this.filterItem }
|
||||||
columns={ columns }
|
columns={ columns }
|
||||||
bulk_actions={ bulk_actions }
|
bulk_actions={ bulk_actions }
|
||||||
item_actions={ item_actions }
|
item_actions={ item_actions }
|
||||||
|
42
lib/Config/Hooks.php
Normal file
42
lib/Config/Hooks.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Config;
|
||||||
|
|
||||||
|
class Hooks {
|
||||||
|
function __construct() {
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
// WP Users synchronization
|
||||||
|
add_action(
|
||||||
|
'user_register',
|
||||||
|
'\MailPoet\Filters\WP::synchronizeUser',
|
||||||
|
1
|
||||||
|
);
|
||||||
|
add_action(
|
||||||
|
'added_existing_user',
|
||||||
|
'\MailPoet\Filters\WP::synchronizeUser',
|
||||||
|
1
|
||||||
|
);
|
||||||
|
add_action(
|
||||||
|
'profile_update',
|
||||||
|
'\MailPoet\Filters\WP::synchronizeUser',
|
||||||
|
1
|
||||||
|
);
|
||||||
|
add_action(
|
||||||
|
'delete_user',
|
||||||
|
'\MailPoet\Filters\WP::synchronizeUser',
|
||||||
|
1
|
||||||
|
);
|
||||||
|
// multisite
|
||||||
|
add_action(
|
||||||
|
'deleted_user',
|
||||||
|
'\MailPoet\Filters\WP::synchronizeUser',
|
||||||
|
1
|
||||||
|
);
|
||||||
|
add_action(
|
||||||
|
'remove_user_from_blog',
|
||||||
|
'\MailPoet\Filters\WP::synchronizeUser',
|
||||||
|
1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,8 @@ class Initializer {
|
|||||||
$this->setupAnalytics();
|
$this->setupAnalytics();
|
||||||
$this->setupPermissions();
|
$this->setupPermissions();
|
||||||
$this->setupChangelog();
|
$this->setupChangelog();
|
||||||
|
|
||||||
|
$this->setupHooks();
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupDB() {
|
function setupDB() {
|
||||||
@ -41,6 +43,8 @@ class Initializer {
|
|||||||
$newsletters = Env::$db_prefix . 'newsletters';
|
$newsletters = Env::$db_prefix . 'newsletters';
|
||||||
$newsletter_templates = Env::$db_prefix . 'newsletter_templates';
|
$newsletter_templates = Env::$db_prefix . 'newsletter_templates';
|
||||||
$segments = Env::$db_prefix . 'segments';
|
$segments = Env::$db_prefix . 'segments';
|
||||||
|
$filters = Env::$db_prefix . 'filters';
|
||||||
|
$segment_filter = Env::$db_prefix . 'segment_filter';
|
||||||
$forms = Env::$db_prefix . 'forms';
|
$forms = Env::$db_prefix . 'forms';
|
||||||
$subscriber_segment = Env::$db_prefix . 'subscriber_segment';
|
$subscriber_segment = Env::$db_prefix . 'subscriber_segment';
|
||||||
$newsletter_segment = Env::$db_prefix . 'newsletter_segment';
|
$newsletter_segment = Env::$db_prefix . 'newsletter_segment';
|
||||||
@ -53,6 +57,8 @@ class Initializer {
|
|||||||
define('MP_SETTINGS_TABLE', $settings);
|
define('MP_SETTINGS_TABLE', $settings);
|
||||||
define('MP_NEWSLETTERS_TABLE', $newsletters);
|
define('MP_NEWSLETTERS_TABLE', $newsletters);
|
||||||
define('MP_SEGMENTS_TABLE', $segments);
|
define('MP_SEGMENTS_TABLE', $segments);
|
||||||
|
define('MP_FILTERS_TABLE', $filters);
|
||||||
|
define('MP_SEGMENT_FILTER_TABLE', $segment_filter);
|
||||||
define('MP_FORMS_TABLE', $forms);
|
define('MP_FORMS_TABLE', $forms);
|
||||||
define('MP_SUBSCRIBER_SEGMENT_TABLE', $subscriber_segment);
|
define('MP_SUBSCRIBER_SEGMENT_TABLE', $subscriber_segment);
|
||||||
define('MP_NEWSLETTER_TEMPLATES_TABLE', $newsletter_templates);
|
define('MP_NEWSLETTER_TEMPLATES_TABLE', $newsletter_templates);
|
||||||
@ -110,4 +116,10 @@ class Initializer {
|
|||||||
$changelog = new Changelog();
|
$changelog = new Changelog();
|
||||||
$changelog->init();
|
$changelog->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setupHooks() {
|
||||||
|
$hooks = new Hooks();
|
||||||
|
$hooks->init();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@ class Migrator {
|
|||||||
'newsletters',
|
'newsletters',
|
||||||
'newsletter_templates',
|
'newsletter_templates',
|
||||||
'segments',
|
'segments',
|
||||||
|
'filters',
|
||||||
|
'segment_filter',
|
||||||
'subscriber_segment',
|
'subscriber_segment',
|
||||||
'newsletter_segment',
|
'newsletter_segment',
|
||||||
'custom_fields',
|
'custom_fields',
|
||||||
@ -50,6 +52,7 @@ class Migrator {
|
|||||||
function subscribers() {
|
function subscribers() {
|
||||||
$attributes = array(
|
$attributes = array(
|
||||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||||
|
'wp_user_id bigint(20) NULL,',
|
||||||
'first_name tinytext NOT NULL,',
|
'first_name tinytext NOT NULL,',
|
||||||
'last_name tinytext NOT NULL,',
|
'last_name tinytext NOT NULL,',
|
||||||
'email varchar(150) NOT NULL,',
|
'email varchar(150) NOT NULL,',
|
||||||
@ -106,14 +109,40 @@ class Migrator {
|
|||||||
|
|
||||||
function segments() {
|
function segments() {
|
||||||
$attributes = array(
|
$attributes = array(
|
||||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||||
'name varchar(90) NOT NULL,',
|
'name varchar(90) NOT NULL,',
|
||||||
'description varchar(250) NOT NULL,',
|
'description varchar(250) NOT NULL,',
|
||||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||||
'deleted_at TIMESTAMP NULL DEFAULT NULL,',
|
'deleted_at TIMESTAMP NULL DEFAULT NULL,',
|
||||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||||
'PRIMARY KEY (id),',
|
'PRIMARY KEY (id),',
|
||||||
'UNIQUE KEY name (name)'
|
'UNIQUE KEY name (name)'
|
||||||
|
);
|
||||||
|
return $this->sqlify(__FUNCTION__, $attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filters() {
|
||||||
|
$attributes = array(
|
||||||
|
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||||
|
'name varchar(90) NOT NULL,',
|
||||||
|
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||||
|
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||||
|
'PRIMARY KEY (id),',
|
||||||
|
'UNIQUE KEY name (name)'
|
||||||
|
);
|
||||||
|
return $this->sqlify(__FUNCTION__, $attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
function segment_filter() {
|
||||||
|
$attributes = array(
|
||||||
|
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||||
|
'segment_id mediumint(9) NOT NULL,',
|
||||||
|
'filter_id mediumint(9) NOT NULL,',
|
||||||
|
'params longtext NULL,',
|
||||||
|
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||||
|
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||||
|
'PRIMARY KEY (id),',
|
||||||
|
'UNIQUE KEY segment_filter (segment_id,filter_id)'
|
||||||
);
|
);
|
||||||
return $this->sqlify(__FUNCTION__, $attributes);
|
return $this->sqlify(__FUNCTION__, $attributes);
|
||||||
}
|
}
|
||||||
|
55
lib/Filters/WP.php
Normal file
55
lib/Filters/WP.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Filters;
|
||||||
|
use \MailPoet\Models\Subscriber;
|
||||||
|
use \MailPoet\Models\Segment;
|
||||||
|
use \MailPoet\Models\SubscriberSegment;
|
||||||
|
|
||||||
|
class WP {
|
||||||
|
static function synchronizeUser($wp_user_id) {
|
||||||
|
$wpUser = \get_userdata($wp_user_id);
|
||||||
|
if($wpUser === false) return;
|
||||||
|
|
||||||
|
$subscriber = Subscriber::where('wp_user_id', $wpUser->ID)
|
||||||
|
->findOne();
|
||||||
|
|
||||||
|
switch(current_filter()) {
|
||||||
|
case 'user_register':
|
||||||
|
case 'added_existing_user':
|
||||||
|
case 'profile_update':
|
||||||
|
// get first name & last name
|
||||||
|
$first_name = $wpUser->first_name;
|
||||||
|
$last_name = $wpUser->last_name;
|
||||||
|
if(empty($wpUser->first_name) && empty($wpUser->last_name)) {
|
||||||
|
$first_name = $wpUser->display_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// subscriber data
|
||||||
|
$data = array(
|
||||||
|
'wp_user_id'=> $wpUser->ID,
|
||||||
|
'email' => $wpUser->user_email,
|
||||||
|
'first_name' => $first_name,
|
||||||
|
'last_name' => $last_name,
|
||||||
|
'status' => 'subscribed'
|
||||||
|
);
|
||||||
|
|
||||||
|
if($subscriber !== false) {
|
||||||
|
$data['id'] = $subscriber->id();
|
||||||
|
}
|
||||||
|
$subscriber = Subscriber::createOrUpdate($data);
|
||||||
|
|
||||||
|
if($subscriber !== false && $subscriber->id()) {
|
||||||
|
$segment = Segment::getWPUsers();
|
||||||
|
$segment->addSubscriber($subscriber->id());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete_user':
|
||||||
|
case 'deleted_user':
|
||||||
|
case 'remove_user_from_blog':
|
||||||
|
if($subscriber !== false && $subscriber->id()) {
|
||||||
|
$subscriber->delete();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
lib/Models/Filter.php
Normal file
50
lib/Models/Filter.php
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Models;
|
||||||
|
|
||||||
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class Filter extends Model {
|
||||||
|
static $_table = MP_FILTERS_TABLE;
|
||||||
|
|
||||||
|
function __construct() {
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
$this->addValidations('name', array(
|
||||||
|
'required' => __('You need to specify a name.')
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
function delete() {
|
||||||
|
// delete all relations to subscribers
|
||||||
|
SegmentFilter::where('filter_id', $this->id)->deleteMany();
|
||||||
|
return parent::delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
function segments() {
|
||||||
|
return $this->has_many_through(
|
||||||
|
__NAMESPACE__.'\Segment',
|
||||||
|
__NAMESPACE__.'\SegmentFilter',
|
||||||
|
'filter_id',
|
||||||
|
'segment_id'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function createOrUpdate($data = array()) {
|
||||||
|
$filter = false;
|
||||||
|
|
||||||
|
if(isset($data['id']) && (int)$data['id'] > 0) {
|
||||||
|
$filter = self::findOne((int)$data['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($filter === false) {
|
||||||
|
$filter = self::create();
|
||||||
|
$filter->hydrate($data);
|
||||||
|
} else {
|
||||||
|
unset($data['id']);
|
||||||
|
$filter->set($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
$filter->save();
|
||||||
|
return $filter;
|
||||||
|
}
|
||||||
|
}
|
@ -38,6 +38,15 @@ class Segment extends Model {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function segmentFilters() {
|
||||||
|
return $this->has_many_through(
|
||||||
|
__NAMESPACE__.'\Filter',
|
||||||
|
__NAMESPACE__.'\SegmentFilter',
|
||||||
|
'segment_id',
|
||||||
|
'filter_id'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function duplicate($data = array()) {
|
function duplicate($data = array()) {
|
||||||
$duplicate = parent::duplicate($data);
|
$duplicate = parent::duplicate($data);
|
||||||
|
|
||||||
@ -67,6 +76,10 @@ class Segment extends Model {
|
|||||||
->delete();
|
->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function getWPUsers() {
|
||||||
|
return self::findOne(1);
|
||||||
|
}
|
||||||
|
|
||||||
static function search($orm, $search = '') {
|
static function search($orm, $search = '') {
|
||||||
return $orm->whereLike('name', '%'.$search.'%');
|
return $orm->whereLike('name', '%'.$search.'%');
|
||||||
}
|
}
|
||||||
|
12
lib/Models/SegmentFilter.php
Normal file
12
lib/Models/SegmentFilter.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Models;
|
||||||
|
|
||||||
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class SegmentFilter extends Model {
|
||||||
|
public static $_table = MP_SEGMENT_FILTER_TABLE;
|
||||||
|
|
||||||
|
function __construct() {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
}
|
@ -324,7 +324,7 @@ class Subscriber extends Model {
|
|||||||
->whereNull('deleted_at')
|
->whereNull('deleted_at')
|
||||||
->where('status', 'unconfirmed');
|
->where('status', 'unconfirmed');
|
||||||
}
|
}
|
||||||
|
|
||||||
static function createMultiple($columns, $values) {
|
static function createMultiple($columns, $values) {
|
||||||
return self::rawExecute(
|
return self::rawExecute(
|
||||||
'INSERT INTO `' . self::$_table . '` ' .
|
'INSERT INTO `' . self::$_table . '` ' .
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
namespace MailPoet\Router;
|
namespace MailPoet\Router;
|
||||||
use \MailPoet\Models\Segment;
|
use \MailPoet\Models\Segment;
|
||||||
use \MailPoet\Models\SubscriberSegment;
|
use \MailPoet\Models\SubscriberSegment;
|
||||||
|
use \MailPoet\Models\SegmentFilter;
|
||||||
use \MailPoet\Listing;
|
use \MailPoet\Listing;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
@ -31,6 +32,18 @@ class Segments {
|
|||||||
|
|
||||||
// fetch segments relations for each returned item
|
// fetch segments relations for each returned item
|
||||||
foreach($listing_data['items'] as &$item) {
|
foreach($listing_data['items'] as &$item) {
|
||||||
|
$item['filters'] = SegmentFilter::table_alias('relation')
|
||||||
|
->where(
|
||||||
|
'relation.segment_id',
|
||||||
|
$item['id']
|
||||||
|
)
|
||||||
|
->join(
|
||||||
|
MP_FILTERS_TABLE,
|
||||||
|
'filters.id = relation.filter_id',
|
||||||
|
'filters'
|
||||||
|
)
|
||||||
|
->findArray();
|
||||||
|
|
||||||
$stats = SubscriberSegment::table_alias('relation')
|
$stats = SubscriberSegment::table_alias('relation')
|
||||||
->where(
|
->where(
|
||||||
'relation.segment_id',
|
'relation.segment_id',
|
||||||
|
Reference in New Issue
Block a user