Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,444 @@
<?php
class OPanda_LeadsListTable extends WP_List_Table
{
public function __construct( $options = array() ) {
$options['singular'] = __( 'Lead', 'bizpanda' );
$options['plural'] = __( 'Leads', 'bizpanda' );
$options['ajax'] = false;
parent::__construct( $options );
$this->bulk_delete();
}
public function get_views() {
$counts = OPanda_Leads::getCountByStatus();
$link = 'edit.php?post_type=' . OPANDA_POST_TYPE . '&page=leads-bizpanda';
$currentStatus = isset( $_GET['opanda_status'] ) ? $_GET['opanda_status'] : 'all';
if ( !in_array( $currentStatus, array('all', 'confirmed', 'not-confirmed') ) ) $currentStatus = 'all';
$items = array(
'view-all' => array(
'title' => __('All', 'bizpanda'),
'link' => $link,
'count' => array_sum($counts),
'current' => $currentStatus == 'all'
),
'view-confirmed' => array(
'title' => __('Confirmed', 'bizpanda'),
'link' => add_query_arg( 'opanda_status', 'confirmed', $link ),
'count' => $counts['confirmed'],
'current' => $currentStatus == 'confirmed'
),
'view-not-confirmed' => array(
'title' => __('Not Confirmed', 'bizpanda'),
'link' => add_query_arg( 'opanda_status', 'not-confirmed', $link ),
'count' => $counts['not-confirmed'],
'current' => $currentStatus == 'not-confirmed'
)
);
$views = array();
foreach( $items as $name => $data ) {
$views[$name] = "<a href='" . $data['link'] . "' class='" . ( $data['current'] ? 'current' : '' ) . "'>" . $data['title'] . " <span class='count'>(" . number_format_i18n( $data['count'] ) . ")</span></a>";
}
return $views;
}
public function no_items() {
echo __( 'No leads found. ', 'bizpanda');
$view = isset( $_GET['opanda_status'] ) ? $_GET['opanda_status'] : 'all';
if ( 'all' !== $view ) return;
if ( BizPanda::isSinglePlugin() ) {
if ( BizPanda::hasPlugin('optinpanda') ) {
printf('To start generating leads, create <a href="%s"><strong>Email Locker</strong></a> or <a href="%s"><strong>Sign-In Locker</strong></a> and lock with them some content on your website.', opanda_get_help_url('what-is-email-locker'), opanda_get_help_url('what-is-signin-locker'));
} else {
printf('To start generating leads, create <a href="%s"><strong>Sign-In Locker</strong></a> and lock with it some content on your website.', opanda_get_help_url('what-is-signin-locker'));
}
} else {
printf('To start generating leads, create <a href="%s"><strong>Email Locker</strong></a> or <a href="%s"><strong>Sign-In Locker</strong></a> and lock with them some content on your website.', opanda_get_help_url('what-is-email-locker'), opanda_get_help_url('what-is-signin-locker'));
}
}
public function search_box($text, $input_id) {
if( !count($this->items) && !isset($_GET['s']) ) return;
$postType = isset( $_GET['post_type'] ) ? htmlspecialchars( $_GET['post_type'] ) : '';
$page = isset( $_GET['page'] ) ? htmlspecialchars( $_GET['page'] ) : '';
$currentStatus = isset( $_GET['opanda_status'] ) ? htmlspecialchars( $_GET['opanda_status'] ) : 'all';
if ( !in_array( $currentStatus, array('all', 'confirmed', 'not-confirmed') ) ) $currentStatus = 'all';
$s = isset( $_GET['s'] ) ? htmlspecialchars( $_GET['s'] ) : '';
?>
<form id="searchform" action method="GET">
<?php if(isset($_GET['post_type'])) : ?><input type="hidden" name="post_type" value="<?php echo $postType ?>"><?php endif; ?>
<?php if(isset($_GET['page'])) : ?><input type="hidden" name="page" value="<?php echo $page ?>"><?php endif; ?>
<?php if(isset($_GET['opanda_status'])) : ?><input type="hidden" name="opanda_status" value="<?php echo $currentStatus ?>"><?php endif; ?>
<p class="search-box">
<label class="screen-reader-text" for="sa-search-input"><?php echo $text; ?></label>
<input type="search" id="<?php echo $input_id ?>" name="s" value="<?php echo $s ?>">
<input type="submit" name="" id="search-submit" class="button" value="<?php echo $text; ?>">
</p>
</form>
<?php
}
/**
* Define the columns that are going to be used in the table
* @return array $columns, the array of columns to use with the table
*/
function get_columns() {
return $columns = array(
'cb' => '<input type="checkbox" />',
'avatar' => '',
'name' => __('Name', 'bizpanda'),
'channel' => __('Channel', 'bizpanda'),
'added' => __('Added', 'bizpanda'),
'status' => __('Status', 'bizpanda'),
);
}
/**
* Decide which columns to activate the sorting functionality on
* @return array $sortable, the array of columns that can be sorted by the user
*/
public function get_sortable_columns() {
return array(
'name' => 'name',
'channel' => 'channel',
'added' => 'added',
'status' => 'status'
);
}
public function get_bulk_actions() {
$actions = array(
'delete' => __('Delete', 'mymail')
);
return $actions;
}
/**
* Checks and runs the bulk action 'delete'.
*/
public function bulk_delete() {
$action = $this->current_action();
if ( 'delete' !== $action ) return;
if ( empty( $_POST['opanda_leads'] ) ) return;
$ids = array();
foreach( $_POST['opanda_leads'] as $leadId ) {
$ids[] = intval( $leadId );
}
global $wpdb;
$wpdb->query("DELETE FROM {$wpdb->prefix}opanda_leads WHERE ID IN (" . implode(',', $ids) . ")");
$wpdb->query("DELETE FROM {$wpdb->prefix}opanda_leads_fields WHERE lead_id IN (" . implode(',', $ids) . ")");
}
/**
* Prepare the table with different parameters, pagination, columns and table elements
*/
function prepare_items() {
global $wpdb;
$query = "SELECT * FROM {$wpdb->prefix}opanda_leads";
// where
$where = array();
if ( isset( $_GET['opanda_status'] ) && in_array( $_GET['opanda_status'], array('confirmed', 'not-confirmed') ) ) {
$where[] = 'lead_email_confirmed = ' . ( ( $_GET['opanda_status'] == 'confirmed' ) ? '1' : '0' );
}
if ( isset( $_GET['s'] ) ) {
$search = trim(addcslashes(esc_sql($_GET['s']), '%_'));
$search = explode(' ', $search);
$searchSql = " (";
$terms = array();
foreach($search as $term){
if(substr($term, 0,1) == '-'){
$term = substr($term,1);
$operator = 'AND';
$like = 'NOT LIKE';
$end = '(1=1)';
}else{
$operator = 'OR';
$like = 'LIKE';
$end = '(1=0)';
}
$termsql = " ( ";
$termsql .= " (lead_display_name $like '%".$term."%') $operator ";
$termsql .= " (lead_name $like '%".$term."%') $operator ";
$termsql .= " (lead_family $like '%".$term."%') $operator ";
$termsql .= " (lead_email $like '%".$term."%') $operator ";
$termsql .= " $end )";
$terms[] = $termsql;
}
$searchSql .= implode(' AND ', $terms) .')';
$where[] = $searchSql;
}
if ( !empty( $where ) ) {
$query .= ' WHERE ' . implode(' AND ', $where);
}
// order
$allowed = apply_filters( 'opanda_leads_allowed_orderby_columns', array( 'name', 'channel', 'added', 'status' ) );
$orderby = !empty($_GET["orderby"]) ? $_GET["orderby"] : 'added';
if ( !in_array( $orderby, $allowed ) ) $orderby = 'added';
$order = !empty($_GET["order"]) ? $_GET["order"] : 'desc';
if ( !in_array( $orderby, array('asc','desc') ) ) $order = 'desc';
if ( 'name' === $orderby ) $dbOrderBy = array( 'lead_display_name', 'lead_email');
elseif ( 'channel' === $orderby ) $dbOrderBy = array( 'lead_item_id' );
elseif ( 'added' === $orderby ) $dbOrderBy = array( 'lead_date' );
elseif ( 'status' === $orderby ) $dbOrderBy = array( 'lead_confirmed' );
else $dbOrderBy = array( $orderby );
foreach( $dbOrderBy as $index => $orderField ) {
$dbOrderBy[$index] .= ' ' . strtoupper( $order );
}
if( !empty($dbOrderBy) & !empty($order) )
$query.=' ORDER BY ' . implode ( ', ', $dbOrderBy );
$totalitems = $wpdb->get_var(str_replace("SELECT *", "SELECT COUNT(id)", $query));
$perpage = 20;
$paged = !empty($_GET["paged"]) ? intval($_GET["paged"]) : 1;
if(empty($paged) || !is_numeric($paged) || $paged<=0 ){ $paged=1; }
$totalpages = ceil($totalitems/$perpage);
if(!empty($paged) && !empty($perpage)){
$offset=($paged-1)*$perpage;
$query.=' LIMIT '.(int)$offset.','.(int)$perpage;
}
$this->set_pagination_args( array(
"total_items" => $totalitems,
"total_pages" => $totalpages,
"per_page" => $perpage,
));
$this->items = $wpdb->get_results($query);
}
/**
* Shows a checkbox.
*
* @since 1.0.7
* @return void
*/
public function column_cb($record) {
return sprintf(
'<input type="checkbox" name="opanda_leads[]" value="%s" />', $record->ID
);
}
/**
* Shows an avatar of the lead.
*
* @since 1.0.7
* @return void
*/
public function column_avatar($record) {
$url = admin_url('/edit.php?post_type=opanda-item&page=leads-bizpanda&action=leadDetails&leadID=' . $record->ID);
$avatar = '';
if ( !empty( $url ) ) $avatar .= '<a href="' .$url . '" class="opanda-avatar">';
else $avatar .= '<span class="opanda-avatar">';
$avatar .= OPanda_Leads::getAvatar( $record->ID, $record->lead_email, 40 );
if ( !empty( $url ) ) $avatar .= '</a>';
else $avatar .= '</span>';
echo $avatar;
}
/**
* Shows a name of the lead.
*
* @since 1.0.7
* @return void
*/
public function column_name($record) {
$name = '';
$url = admin_url('/edit.php?post_type=opanda-item&page=leads-bizpanda&action=leadDetails&leadID=' . $record->ID);
if ( !empty( $url ) ) $name .= '<a href="' . $url . '" class="opanda-name">';
else $name .= '<strong class="opanda-name">';
if ( !empty( $record->lead_display_name ) ) {
$name .= htmlspecialchars( $record->lead_display_name );
} else {
$name .= htmlspecialchars( $record->lead_email );
}
if ( !empty( $url ) ) $name .= '</a>';
else $name .= '</strong>';
/**
Social Icons
*/
$fields = OPanda_Leads::getLeadFields( $record->ID );
if ( isset( $fields['facebookUrl'] ) ) {
$name .= sprintf( '<a href="%s" target="_blank" class="opanda-social-icon opanda-facebook-icon"><i class="fa fa-facebook"></i></a>', $fields['facebookUrl'] );
}
if ( isset( $fields['twitterUrl'] ) ) {
$name .= sprintf( '<a href="%s" target="_blank" class="opanda-social-icon opanda-twitter-icon"><i class="fa fa-twitter"></i></a>', $fields['twitterUrl'] );
}
if ( isset( $fields['googleUrl'] ) ) {
$name .= sprintf( '<a href="%s" target="_blank" class="opanda-social-icon opanda-google-icon"><i class="fa fa-google-plus"></i></a>', $fields['googleUrl'] );
}
if ( isset( $fields['linkedinUrl'] ) ) {
$name .= sprintf( '<a href="%s" target="_blank" class="opanda-social-icon opanda-linkedin-icon"><i class="fa fa-linkedin"></i></a>', $fields['linkedinUrl'] );
}
/**/
if ( !empty( $record->lead_display_name ) ) {
$name .= '<br />' . $record->lead_email;
}
echo $name;
}
/**
* Shows how the lead was generated.
*
* @since 1.0.7
* @return void
*/
public function column_channel($record) {
$itemId = $record->lead_item_id;
$itemTitle = $record->lead_item_title;
$item = get_post( $itemId );
$itemTitle = empty( $item )
? '<i>' . __('(unknown)', 'bizpanda') . '</i>'
: $item->post_title;
$via = empty( $item )
? $itemTitle
: '<a href="' . opanda_get_admin_url('stats', array('opanda_id' => $itemId)) . '"><strong>' . $itemTitle. '</strong></a>';
$via = sprintf( __("Via: %s", 'bizpanda'), $via );
$postUrl = $record->lead_referer;
$postTitle = $record->lead_post_title;
$post = get_post( $record->lead_post_id );
if ( !empty( $post) ){
$postUrl = get_permalink( $post->ID );
$postTitle = $post->post_title;
}
if ( empty( $postTitle) ) $postTitle = '<i>' . __('(no title)', 'bizpanda') . '</i>';
$referer = '<a href="' . $postUrl . '"><strong>' . $postTitle . '</strong></a>';
$where = sprintf( __("On Page: %s", 'bizpanda'), $referer );
$text = $via . '<br />' . $where;
echo $text;
}
/**
* Shows when the lead was added.
*
* @since 1.0.7
* @return void
*/
public function column_added($record) {
echo date_i18n( get_option('date_format') . ' ' . get_option('time_format'), $record->lead_date + (get_option('gmt_offset')*3600));
}
/**
* Shows a status of the lead.
*
* @since 1.0.7
* @return void
*/
public function column_status($record) {
if ( BizPanda::hasPlugin('optinpanda') ) {
if ( $record->lead_email_confirmed) { ?>
<span class="opanda-status-help" title="<?php _e('This email is real. It was received from social networks or the user confirmed it by clicking on the link inside the confirmation email.', 'bizpanda') ?>">
<i class="fa fa-check-circle-o"></i><i><?php _e('email', 'optinapnda') ?></i>
</span>
<?php } else { ?>
<span class="opanda-status-help" title="<?php _e('This email was not confirmed. It means that actually this email address may be owned by another user.', 'bizpanda') ?>">
<i class="fa fa-circle-o"></i><i><?php _e('email', 'optinapnda') ?></i>
</span>
<?php }
echo '<br />';
if ( $record->lead_subscription_confirmed) { ?>
<span class="opanda-status-help" title="<?php _e('This user confirmed his subscription.', 'bizpanda') ?>">
<i class="fa fa-check-circle-o"></i><i><?php _e('subscription', 'optinapnda') ?></i>
</span>
<?php } else { ?>
<span class="opanda-status-help" title="<?php _e('This user has not confirmed his subscription.', 'bizpanda') ?>">
<i class="fa fa-circle-o"></i><i><?php _e('subscription', 'optinapnda') ?></i>
</span>
<?php }
} else {
if ( $record->lead_email_confirmed) { ?>
<span class="opanda-status-help" title="<?php _e('This email is real. It was received from social networks.', 'bizpanda') ?>">
<i class="fa fa-check-circle-o"></i><i><?php _e('email', 'optinapnda') ?></i>
</span>
<?php } else { ?>
<span class="opanda-status-help" title="<?php _e('This email was not confirmed. It means that actually this email address may be owned by another user.', 'bizpanda') ?>">
<i class="fa fa-circle-o"></i><i><?php _e('email', 'optinapnda') ?></i>
</span>
<?php }
}
}
public function column_default( $item, $column_name ) {
$value = '';
return apply_filters('opanda_leads_column', $value, $item, $column_name );
}
}

View File

@@ -0,0 +1,163 @@
<?php
class OPanda_ItemsViewTable extends FactoryViewtables320_Viewtable
{
public function configure()
{
/**
* Columns
*/
$this->columns->clear();
$this->columns->add('stats', __('<span title="Unlocks / Impressions / Conversion">U / I / %', 'bizpanda'));
$this->columns->add('title', __('Locker Title', 'bizpanda'));
if ( !BizPanda::isSinglePlugin() ) {
$this->columns->add('type', __('Type', 'bizpanda'));
}
$this->columns->add('shortcode', __('Shortcode', 'bizpanda'));
$this->columns->add('theme', __('Theme', 'bizpanda'));
$this->columns->add('bulk', __('Bulk Lock', 'bizpanda'));
$this->columns->add('visibility', __('Visibility Conditions', 'bizpanda'));
/**
* Scripts & styles
*/
$this->scripts->add(OPANDA_BIZPANDA_URL . '/assets/admin/js/item-view.010000.js');
$this->styles->add(OPANDA_BIZPANDA_URL . '/assets//admin/css/item-view.010000.css');
}
/**
* Column 'Title'
*/
public function columnTitle( $post, $isFullMode ) {
if ($isFullMode ) {
$url = get_post_meta($post->ID, 'opanda_theme', true);
if ( empty($url) ) $url = '<i>[current page]</i>';
echo '<p>' . $post->post_title . '</p>';
echo '<p>' . $url . '</p>';
} else {
echo $post->post_title;
}
}
/**
* Column 'Type'
*/
public function columnType( $post, $isFullMode ) {
$item = get_post_meta($post->ID, 'opanda_item', true);
echo $item;
}
/**
* Column 'Shortcode'
*/
public function columnShortcode( $post, $isFullMode ) {
$isSystem = get_post_meta( $post->ID, 'opanda_is_system', true);
$itemTypeName = get_post_meta( $post->ID, 'opanda_item', true);
$item = OPanda_Items::getItem( $itemTypeName );
$shortcodeName = $item['shortcode'];
$shortcode = '[' . $shortcodeName . '] [/' . $shortcodeName . ']';
if (!$isSystem) $shortcode = '[' . $shortcodeName . ' id="' . $post->ID . '"] [/' . $shortcodeName . ']';
?>
<input class="shortcode" type="text" value='<?php echo $shortcode ?>' />
<?php
}
/**
* Column 'Shortcode'
*/
public function columnBulk( $post, $isFullMode ) {
?>
<div class='onp-sl-inner-wrap'>
<?php opanda_print_bulk_locking_state( $post->ID ); ?>
</div>
<?php
}
/**
* Column 'Theme'
*/
public function columnTheme( $post, $isFullMode ) {
$theme = get_post_meta($post->ID, 'opanda_style', true);
echo $theme;
}
/**
* Column 'Visibility Conditions'
*/
public function columnVisibility( $post, $isFullMode ) {
$mode = get_post_meta($post->ID, 'opanda_visibility_mode', true);
if ( empty( $mode) ) $mode = 'simple';
?>
<div class='onp-sl-inner-wrap'>
<?php if ( $mode === 'simple' ) { ?>
<?php opanda_print_simple_visibility_options( $post->ID ); ?>
<?php } else { ?>
<?php opanda_print_visibility_conditions( $post->ID ); ?>
<?php } ?>
</div>
<?php
}
/**
* Column 'Created'
*/
public function columnStats( $post ) {
global $optinpanda;
$imperessions = intval( get_post_meta($post->ID, 'opanda_imperessions', true) );
$conversion = '0';
$unlocks = intval( get_post_meta($post->ID, 'opanda_unlocks', true) );
if ( !empty( $imperessions )) {
$conversion = round( $unlocks / $imperessions * 100, 2 );
} elseif ( !empty( $unlocks ) ) {
$conversion = 100;
}
$strong = ( $unlocks > 0 );
$url = opanda_get_admin_url('stats', array('opanda_id' => $post->ID));
if ( $strong ) {
echo '<a href="' . $url . '"><strong>' . $unlocks . '</strong> / ' . $imperessions . ' / ' . sprintf( '%.02f', $conversion ) . '%' . '</a>';
} else {
echo '<a href="' . $url . '" class="opanda-empty">' . $unlocks . ' / ' . $imperessions . ' / ' . sprintf( '%.02f', $conversion ) . '%' . '</a>';
}
?>
<?php
}
public function actionPostRowActions( $actions ) {
global $post;
if( $post->post_type !== $this->type->name ) return $actions;
$temporaryActions = array(
'edit' => $actions['edit'],
'clone' => '<a href="' . wp_nonce_url( get_admin_url() . 'post.php?post_type=opanda-item&amp;post=' . $post->ID . '&amp;action=opanda-clone-item', 'opanda-clone-item-nonce' ) . '" title="' . __("Clone this element", 'optinpanda') . '">' . __("Clone", 'bizpanda') . '</a>',
'trash' => $actions['trash']
);
return parent::actionPostRowActions( $temporaryActions );
}
}

View File

@@ -0,0 +1,241 @@
<?php
class OPanda_StatsScreen {
public function __construct( $options ) {
$this->options = $options;
}
public function getChart( $options ) {
require_once (OPANDA_BIZPANDA_DIR . '/admin/includes/stats.php');
$chartData = OPanda_Stats::getChartData( $options );
return new $this->options['chartClass']( $this, $chartData );
}
public function getTable( $options ) {
require_once (OPANDA_BIZPANDA_DIR . '/admin/includes/stats.php');
$tableData = OPanda_Stats::getViewTable( $options );
return new $this->options['tableClass']( $this, $tableData );
}
}
class OPanda_StatsChart {
public $type = 'area';
public function __construct( $screen, $data ) {
$this->screen = $screen;
$this->data = $data;
}
public function getFields() {
return array();
}
public function getSelectors() {
$fields = $this->getFields();
unset($fields['aggregate_date']);
return $fields;
}
public function hasSelectors() {
$selectors = $this->getSelectors();
return !empty( $selectors );
}
public function getSelectorsNames() {
$selectors = $this->getSelectors();
if ( empty( $selectors ) ) return array();
$result = array();
foreach( $selectors as $key => $selector ) {
$result[] = "'" . $key . "'";
}
return $result;
}
public function printData() {
$fields = $this->getFields();
$output = '';
foreach ( $this->data as $rowIndex => $dataRow ) {
$dataToPrint = array();
foreach( $fields as $field => $fieldData) {
if ( 'aggregate_date' == $field ) {
$dataToPrint['date'] = array(
'value' => 'new Date('.$dataRow['year'].','.$dataRow['mon'].','.$dataRow['day'].')'
);
} else {
$dataToPrint[$field] = array(
'value' => $this->getValue( $rowIndex, $field ),
'title' => isset( $fieldData['title'] ) ? $fieldData['title'] : '',
'color' => isset( $fieldData['color'] ) ? $fieldData['color'] : null
);
}
}
$rowDataToPrint = '';
foreach( $dataToPrint as $key => $data ) {
if ( !isset( $data['title'] )) $data['title'] = '';
if ( !isset( $data['color'] )) $data['color'] = '';
$rowDataToPrint .= "'$key': {'value': {$data['value']}, 'title': '{$data['title']}', 'color': '{$data['color']}'},";
}
$rowDataToPrint = rtrim($rowDataToPrint, ',');
$output .= '{' . $rowDataToPrint . '},';
}
$output = rtrim($output, ',');
echo $output;
}
public function getValue( $rowIndex, $fieldName ) {
$camelCase = str_replace('-', ' ', $fieldName);
$camelCase = str_replace('_', ' ', $camelCase);
$camelCase = str_replace(' ', '', ucwords( $camelCase) );
$camelCase[0] = strtoupper($camelCase[0]);
if ( method_exists( $this, 'field' . $camelCase ) ) {
return call_user_func( array( $this, 'field' . $camelCase ), $this->data[$rowIndex], $rowIndex );
} else {
if ( isset( $this->data[$rowIndex][$fieldName] ) ) {
return $this->data[$rowIndex][$fieldName];
} else {
return 0;
}
}
}
}
class OPanda_StatsTable {
public $orderBy = 'unlock';
public function __construct( $screen, $data ) {
$this->screen = $screen;
$this->data = $data;
usort($data['data'], array( $this, '_usort') );
$this->data['data'] = array_reverse($data['data']);
}
public function _usort( $a, $b ) {
$orderBy = $this->orderBy;
if ( !isset( $a[$orderBy] ) && !isset( $b[$orderBy] ) ) return 0;
if ( !isset( $a[$orderBy] ) ) return -1;
if ( !isset( $b[$orderBy] ) ) return 1;
if ( $a[$orderBy] == $b[$orderBy] ) return 0;
return ($a[$orderBy] < $b[$orderBy]) ? -1 : 1;
}
public function getColumns() {
return array();
}
public function getHeaderColumns( $level = 1 ) {
$columns = $this->getColumns();
if ( 2 === $level) {
$result = array();
foreach( $columns as $column ) {
if ( !isset( $column['columns'] ) ) continue;
$result = array_merge( $result, $column['columns'] );
}
return $result;
} else {
foreach( $columns as $n => $column ) {
$columns[$n]['rowspan'] = isset( $column['columns'] ) ? 1 : 2;
$columns[$n]['colspan'] = isset( $column['columns'] ) ? count( $column['columns'] ) : 1;
}
return $columns;
}
}
public function hasComplexColumns() {
$columns = $this->getHeaderColumns( 2 );
return !empty( $columns );
}
public function getDataColumns() {
$result = array();
foreach( $this->getColumns() as $name => $column ) {
if ( isset( $column['columns'] ) ) {
$result = array_merge( $result, $column['columns'] );
} else {
$result[$name] = $column;
}
}
return $result;
}
public function getColumnsCount() {
return count( $this->getColumns() );
}
public function getRowsCount() {
return count( $this->data['data'] );
}
public function printValue( $rowIndex, $columnName, $column ) {
$camelCase = str_replace('-', ' ', $columnName);
$camelCase = str_replace('_', ' ', $camelCase);
$camelCase = str_replace(' ', '', ucwords( $camelCase) );
$camelCase[0] = strtoupper($camelCase[0]);
if ( method_exists( $this, 'column' . $camelCase ) ) {
call_user_func( array( $this, 'column' . $camelCase ), $this->data['data'][$rowIndex], $rowIndex );
} else {
$value = isset( $this->data['data'][$rowIndex][$columnName] ) ? $this->data['data'][$rowIndex][$columnName] : 0;
if ( isset( $column['prefix'] ) && $value !== 0 ) echo $column['prefix'] ;
echo $value;
}
}
public function columnIndex( $row, $rowIndex ) {
echo $rowIndex + 1;
}
public function columnTitle( $row ) {
$title = !empty( $row['title'] ) ? $row['title'] : '<i>' . __('(untitled post)', 'bizpanda') . '</i>';
if ( !empty( $row['id'] ) ) {
echo '<a href="' . get_permalink( $row['id'] ) . '" target="_blank">' . $title . ' </a>';
} else {
echo $title;
}
}
public function columnConversion( $row ) {
if ( !isset( $row['impress'] )) $row['impress'] = 0;
if ( !isset( $row['unlock'] )) $row['unlock'] = 0;
if ( $row['impress'] == 0 ) { echo '0%'; return;}
if ( $row['unlock'] > $row['impress'] ) { echo '100%'; return;}
echo ( ceil( $row['unlock'] / $row['impress'] * 10000 ) / 100 ) . '%';
}
}

View File

@@ -0,0 +1,234 @@
<?php
abstract class OPanda_Subscription {
public $name;
public $title;
public $data;
public $deliveryError;
public function __construct( $data = array() ) {
$this->data = $data;
if ( isset( $data['name']) ) $this->name = $data['name'];
if ( isset( $data['title']) ) $this->title = $data['title'];
}
public function isEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL);
}
public function isTransactional() {
return isset( $this->data['transactional'] ) && $this->data['transactional'];
}
public function hasSingleOptIn() {
return in_array('quick', $this->data['modes'] );
}
public abstract function getLists();
public abstract function subscribe( $identityData, $listId, $doubleOptin, $contextData, $verified );
public abstract function check( $identityData, $listId, $contextData );
public abstract function getCustomFields( $listId );
public function prepareFieldValueToSave( $mapOptions, $value ) {
return $value;
}
public function getNameFieldIds() {
return array();
}
public function slugify($text, $separator = ' ')
{
// replace non letter or digits by -
$text = preg_replace('~[^\\pL\d]+~u', $separator, $text);
// trim
$text = trim($text, '-');
// transliterate
$text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
// lowercase
$text = strtolower($text);
// remove unwanted characters
$text = preg_replace('~[^-\w]+~', '', $text);
if (empty($text))
{
return 'n-a';
}
return $text;
}
public function refine( $identityData, $clearEmpty = false ) {
if ( empty( $identityData ) ) return $identityData;
unset( $identityData['html'] );
unset( $identityData['label'] );
unset( $identityData['separator'] );
unset( $identityData['name'] );
unset( $identityData['family'] );
unset( $identityData['displayName'] );
unset( $identityData['fullname'] );
if ( $clearEmpty ) {
foreach ($identityData as $key => $value) {
if ( empty($value) ) unset( $identityData[$key] );
}
}
return $identityData;
}
/**
* The function to subscribe an user through Wordpress.
*/
public function wpSubscribe( $identity, $serviceReady, $context, $listId, $verified ) {
require_once OPANDA_BIZPANDA_DIR . '/admin/includes/leads.php';
require_once OPANDA_BIZPANDA_DIR . '/admin/includes/stats.php';
$email = $identity['email'];
if ( empty( $email ) ) {
throw new OPanda_SubscriptionException( __('The email is not specified.','optinpanda') );
}
$temp = array(
'identity' => $identity,
'serviceReady' => $serviceReady,
'context' => $context,
'listId' => $listId,
'verified' => $verified
);
$lead = OPanda_Leads::getByEmail($email);
// already exists
if ( $lead ) {
if ( $lead->lead_subscription_confirmed ) return array('status' => 'subscribed');
OPanda_Leads::setTempData( $lead, $temp );
$this->sendConfirmation( $lead, $context );
return array('status' => 'pending');
} else {
$leadId = OPanda_Leads::add( $identity, $context, $verified, false, $temp );
$lead = OPanda_Leads::getById($leadId);
$lead->lead_email = $email;
$this->sendConfirmation( $lead, $context );
return array('status' => 'pending');
}
}
/**
* The function to subscribe an user through Wordpress.
*/
public function wpCheck( $identity, $serviceReady, $context, $listId, $verified ) {
$email = $identity['email'];
if ( empty( $email ) ) {
throw new OPanda_SubscriptionException( __('The email is not specified.','optinpanda') );
}
$lead = OPanda_Leads::getByEmail($email);
if ( !$lead ) throw new OPanda_SubscriptionException( __('The email is not found. Please try again.','optinpanda') );
return array('status' => $lead->lead_subscription_confirmed ? 'subscribed' : 'pending');
}
/**
* The function sends the confirmation email.
*/
public function sendConfirmation( $lead, $context ) {
if ( empty( $context['itemId'] ) )
throw new OPanda_SubscriptionException( __('Invalid request. Please contact the OnePress support.', 'optinpanda') );
$lockerId = (int)$context['itemId'];
$emailSubject = get_post_meta($lockerId, 'opanda_confirm_email_subject', true);
$emailBody = get_post_meta($lockerId, 'opanda_confirm_email_body', true);
$link = $this->getConfirmationLink($lead, $context);
$emailBody = str_replace('[link]', '<a href="' . $link . '" target="_blank">' . $link . '</a>', $emailBody);
if ( $this->isTransactional() ) {
$this->send( $lead->lead_email, $emailSubject, $emailBody );
} else {
add_action( 'wp_mail_failed', array($this, 'handleDeliveryError') );
add_filter( 'wp_mail_from', array($this, 'mailFrom'), 99 );
add_filter( 'wp_mail_from_name', array($this, 'mailFromName'), 99 );
$this->deliveryError = false;
$headers[] = 'Content-type: text/html; charset=utf-8';
$result = wp_mail( $lead->lead_email, $emailSubject, $emailBody, $headers );
if ( !$result ) {
if ( $this->deliveryError ) throw new OPanda_SubscriptionException( $this->deliveryError->get_error_message() );
else throw new OPanda_SubscriptionException( __('Unable to send a confirmation email to the specified email address.', 'optinpanda') );
}
remove_action('wp_mail_failed', array($this, 'handleDeliveryError'));
remove_action('wp_mail_failed', array($this, 'wp_mail_from'));
remove_action('wp_mail_failed', array($this, 'wp_mail_from_name'));
}
}
public function handleDeliveryError( $error ) {
$this->deliveryError = $error;
}
public function mailFrom( $from ) {
$value = get_option('opanda_sender_email', null);
return empty( $value ) ? $from : $value;
}
public function mailFromName( $fromName ) {
$value = get_option('opanda_sender_name', null);
return empty( $value ) ? $fromName : $value;
}
public function getConfirmationLink( $lead, $context ) {
$uri = $context['postUrl'];
if ( empty( $uri ) ) $uri = home_url();
$code = $lead->lead_confirmation_code;
if ( empty( $code ) ) {
$code = md5( NONCE_SALT . $lead->lead_email . time() );
OPanda_Leads::setConfirmationCode($lead, $code);
}
$args = array(
'opanda_confirm' => 1,
'opanda_lead' => $lead->ID,
'opanda_code' => $code
);
return add_query_arg($args, $uri);
}
}
/**
* A subscription service exception.
*/
class OPanda_SubscriptionException extends Exception {
public function __construct ($message) {
parent::__construct($message, 0, null);
}
}

View File

@@ -0,0 +1,728 @@
<?php
class OPanda_Leads {
/**
* Adds a new lead.
*
* @since 1.0.7
* @param string[] $identity An array of the identity data.
* @param string[] $context An array of the context data.
* @param bool $confirmed Has a lead confirmed one's email address?
* @return int A lead ID.
*/
public static function add( $identity = array(), $context = array(), $emailConfirmed = false, $subscriptionConfirmed = false, $temp = null )
{
$itemId = isset( $context['itemId'] ) ? intval( $context['itemId'] ) : 0;
if ( !empty( $itemId ) && !get_post_meta($itemId, 'opanda_catch_leads', true) ) return false;
require_once OPANDA_BIZPANDA_DIR . '/admin/includes/leads.php';
require_once OPANDA_BIZPANDA_DIR . '/admin/includes/stats.php';
$email = isset( $identity['email'] ) ? $identity['email'] : false;
$lead = self::getByEmail( $email );
return self::save( $lead, $identity, $context, $emailConfirmed, $subscriptionConfirmed, $temp );
}
/**
* Inserts or updates a lead in the database.
*
* @since 1.0.7
* @param objecy $lead A lead to update.
* @param string[] $identity An array of the identity data.
* @param string[] $context An array of the context data.
* @param bool $confirmed Has a lead confirmed one's email address?
* @return int A lead ID.
*/
public static function save( $lead = null, $identity = array(), $context = array(), $emailConfirmed = false, $subscriptionConfirmed = false, $temp = null ) {
global $wpdb;
require_once OPANDA_BIZPANDA_DIR . '/admin/includes/stats.php';
$email = isset( $identity['email'] ) ? $identity['email'] : false;
if ( isset( $identity['social'] ) ) $emailConfirmed = true;
$itemId = isset( $context['itemId'] ) ? intval( $context['itemId'] ) : 0;
$postId = isset( $context['postId'] ) ? intval( $context['postId'] ) : null;
$item = get_post( $itemId );
$itemTitle = !empty( $item ) ? $item->post_title : null;
$postTitle = self::extract('postTitle', $context);
$postUrl = self::extract('postUrl', $context);
$name = self::extract('name', $identity);
$family = self::extract('family', $identity);
$displayName = self::extract('displayName', $identity );
if ( empty( $displayName ) ) {
if ( !empty( $name ) && !empty( $family ) ) {
$displayName = $name . ' ' . $family;
} elseif ( !empty( $name ) ) {
$displayName = $name;
} elseif ( !empty( $family ) ) {
$displayName = $family;
} else {
$displayName = "";
}
}
$leadId = empty( $lead ) ? null : $lead->ID;
$isNew = empty( $leadId ) ? true : false;
// extra fields
$fields = array();
foreach( $identity as $itemName => $itemValue ) {
if ( in_array( $itemName, array( 'email', 'name', 'family', 'displayName' ) ) ) continue;
if ( 'image' === $itemName ) $itemName = 'externalImage';
$fields[trim( $itemName, '{}') ] = array('value' => $itemValue, 'custom' => ( strpos($itemName, '{') === 0 ) ? 1 : 0 );
}
// counts the number of confirmed emails (subscription)
if ( $subscriptionConfirmed && $leadId && !$lead->lead_subscription_confirmed ) {
require_once OPANDA_BIZPANDA_DIR . '/admin/includes/stats.php';
OPanda_Stats::countMetrict( $itemId, $postId, 'email-confirmed');
}
if ( !$leadId ) {
// counts the number of new recivied emails
OPanda_Stats::countMetrict( $itemId, $postId, 'email-received');
$postTitle = html_entity_decode($postTitle);
$postTitle = urldecode($postTitle);
$postTitle = preg_replace('/[^A-Za-z0-9\s\-\.\,]/', '', $postTitle);
$data = array(
'lead_display_name' => $displayName,
'lead_name' => $name,
'lead_family' => $family,
'lead_email' => $email,
'lead_date' => time(),
'lead_item_id' => $itemId,
'lead_post_id' => $postId,
'lead_item_title' => $itemTitle,
'lead_post_title' => $postTitle,
'lead_referer' => $postUrl,
'lead_email_confirmed' => $emailConfirmed ? 1 : 0,
'lead_subscription_confirmed' => $subscriptionConfirmed ? 1 : 0,
'lead_ip' => self::getIP(),
'lead_temp' => !empty( $temp ) ? json_encode( $temp ) : null
);
// else inserts a new lead
$result = $wpdb->insert( $wpdb->prefix . 'opanda_leads', $data, array(
'%s', '%s', '%s', '%s', '%d', '%d', '%d', '%s', '%s', '%s', '%d', '%s', '%s'
));
// sends a notification
if ( get_option('opanda_notify_leads', false) ) {
$receiver = trim ( get_option('opanda_leads_email_receiver') );
$subject = trim ( get_option('opanda_leads_email_subject') );
$message = trim ( get_option('opanda_leads_email_body') );
$post = get_post( $postId );
$locker = get_post( $itemId );
$eventContext = array(
sprintf ( __( 'Locker: %s', 'bizpanda' ), $locker->post_title ),
sprintf ( __( 'Where: <a href="%s">%s</a>', 'bizpanda' ), get_permalink( $postId ), $post->post_title ),
sprintf ( __( 'IP: %s', 'bizpanda' ), self::getIP() )
);
$eventContext = apply_filters('opanda_leads_notification_context', $eventContext);
$eventDetails = array(
sprintf ( __( 'Name: %s', 'bizpanda' ), $data['lead_display_name'] ),
sprintf ( __( 'Email: %s', 'bizpanda' ), $data['lead_email'] )
);
if ( count( $fields ) > 0 ) {
foreach( $fields as $fieldName => $field ) {
if ( !$field['custom'] ) continue;
$eventDetails[] = $fieldName . ': ' . $field['value'];
}
}
$eventDetails = apply_filters('opanda_leads_notification_details', $eventDetails, $data );
$replacements = array(
'sitename' => get_bloginfo('name'),
'siteurl' => get_bloginfo('url'),
'details' => implode('<br />', $eventDetails),
'context' => implode('<br />', $eventContext)
);
foreach( $replacements as $name => $replacement ) {
$subject = str_replace('{'. $name . '}', $replacement, $subject);
$message = str_replace('{'. $name . '}', $replacement, $message);
}
$headers = array();
$headers[] = 'content-type: text/html';
$subject = apply_filters('opanda_leads_notification_subject', $subject, $data );
$message = apply_filters('opanda_leads_notification_message', $message, $data );
wp_mail( $receiver, $subject, $message, $headers );
}
if ( $result ) $leadId = $wpdb->insert_id;
} else {
$data = array(
'lead_display_name' => $displayName,
'lead_email' => $email,
'lead_name' => $name,
'lead_family' => $family,
'lead_email_confirmed' => $emailConfirmed ? 1 : 0,
'lead_subscription_confirmed' => $subscriptionConfirmed ? 1 : 0,
'lead_temp' => !empty( $temp ) ? json_encode( $temp ) : null
);
$formats = array(
'lead_display_name' => '%s',
'lead_email' => '%s',
'lead_name' => '%s',
'lead_family' => '%s',
'lead_email_confirmed' => '%d',
'lead_subscription_confirmed' => '%d',
'lead_temp' => '%s'
);
// to void claring the temp data in sign in locker
// when several actions save a lead
if ( empty( $data['lead_temp'] ) ) {
unset( $data['lead_temp'] );
unset( $formats['lead_temp'] );
}
if ( empty( $displayName ) ) {
unset( $data['lead_display_name'] );
unset( $formats['lead_display_name'] );
}
if ( empty( $name ) ) {
unset( $data['lead_display_name'] );
unset( $formats['lead_display_name'] );
}
if ( empty( $family ) ) {
unset( $data['lead_display_name'] );
unset( $formats['lead_display_name'] );
}
if ( !$emailConfirmed || $lead->lead_email_confirmed ) {
unset( $data['lead_email_confirmed'] );
unset( $formats['lead_email_confirmed'] );
}
if ( !$subscriptionConfirmed || $lead->lead_subscription_confirmed ) {
unset( $data['lead_subscription_confirmed'] );
unset( $formats['lead_subscription_confirmed'] );
}
if ( !empty( $data ) ) {
$where = array(
'ID' => $leadId
);
$wpdb->update( $wpdb->prefix . 'opanda_leads', $data, $where, array_values( $formats ), array( '%s' ));
}
}
// saving extra fields
foreach( $fields as $fieldName => $fieldData ) {
$sql = $wpdb->prepare("
INSERT INTO {$wpdb->prefix}opanda_leads_fields
( lead_id, field_name, field_value, field_custom )
VALUES ( %d, %s, %s, %d ) ON DUPLICATE KEY UPDATE field_value = VALUES(field_value)
", $leadId, $fieldName, $fieldData['value'], $fieldData['custom'] );
$wpdb->query( $sql );
}
self::pushLeadToZapier( $leadId, $isNew );
return $leadId;
}
/**
* Sets a confirmation code for the lead.
*/
public static function setConfirmationCode( $lead, $code ) {
if ( empty( $lead ) ) return;
global $wpdb;
$sql = $wpdb->prepare("
UPDATE {$wpdb->prefix}opanda_leads
SET lead_confirmation_code = %s
WHERE ID = %d
", $code, $lead->ID );
$wpdb->query($sql);
}
/**
* Confirms a lead.
*/
public static function confirm( $emailOrID, $code, $push = false ) {
if ( empty( $emailOrID ) ) return;
if ( is_numeric($emailOrID) ) {
$lead = OPanda_Leads::getById($emailOrID);
} else {
$lead = OPanda_Leads::getByEmail($emailOrID);
}
if ( !$lead || $lead->lead_subscription_confirmed ) return;
if ( empty( $lead ) ) return;
if ( $code !== $lead->lead_confirmation_code ) return;
$temp = !empty( $lead->lead_temp ) ? json_decode( $lead->lead_temp, true ) : null;
$itemId = isset( $temp['context']['itemId'] ) ? $temp['context']['itemId'] : null;
$postId = isset( $temp['context']['postId'] ) ? $temp['context']['postId'] : null;
if ( $push ) {
try {
require_once OPANDA_BIZPANDA_DIR . '/admin/includes/subscriptions.php';
$serviceReady = isset( $temp['serviceReady'] ) ? $temp['serviceReady'] : null;
$context = isset( $temp['context'] ) ? $temp['context'] : null;
$listId = isset( $temp['listId'] ) ? $temp['listId'] : null;
$verified = isset( $temp['verified'] ) ? $temp['verified'] : null;
$service = OPanda_SubscriptionServices::getCurrentService();
if ( empty( $service) ) {
throw new Exception( sprintf( 'The subscription service is not set.' ));
}
$service->subscribe( $serviceReady, $listId, false, $context, $verified );
} catch (Exception $ex) {
printf ( __( "<strong>Error:</strong> %s", 'bizpanda' ), $ex->getMessage() );
exit;
}
}
global $wpdb;
$sql = $wpdb->prepare("
UPDATE {$wpdb->prefix}opanda_leads
SET lead_email_confirmed = 1, lead_subscription_confirmed = 1
WHERE ID = %d
", $lead->ID );
self::pushLeadToZapier( $lead->ID, false );
$wpdb->query($sql);
// counts the number of confirmed emails (subscription)
if ( $lead->ID && !$lead->lead_subscription_confirmed && $itemId && $postId ) {
require_once OPANDA_BIZPANDA_DIR . '/admin/includes/stats.php';
OPanda_Stats::countMetrict( $itemId, $postId, 'email-confirmed');
}
}
/**
* Sends data to Zapier if needed.
*/
public static function pushLeadToZapier( $leadId, $isNew ) {
global $wpdb;
$newLeadHookUrl = trim( get_option('opanda_zapier_hook_new_leads', "" ) );
if ( empty( $newLeadHookUrl )) return;
if ( empty( $leadId ) ) return;
$lead = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}opanda_leads WHERE ID = %d", $leadId ) );
if ( empty( $lead ) ) return;
$fields = self::getCustomFields( $leadId );
$onlyNewLeads = get_option('opanda_zapier_only_new', false );
$onlyConfirmed = get_option('opanda_zapier_only_confirmed', false );
if ( !(( $onlyNewLeads && $isNew ) || !$onlyNewLeads ) ) return;
if ( !(( $onlyConfirmed && $lead->lead_subscription_confirmed ) || !$onlyConfirmed ) ) return;
$zapierData = array(
'lead_email' => $lead->lead_email,
'lead_name' => $lead->lead_name,
'lead_family' => $lead->lead_family,
'lead_display_name' => $lead->lead_display_name,
'lead_ip' => $lead->lead_ip,
'post_title' => $lead->lead_post_title,
'post_url' => $lead->lead_referer
);
if ( !empty( $fields ) ) {
foreach( $fields as $name => $value ) {
$zapierData['custom_' . $name] = $value;
}
}
$zapierData = apply_filters('opanda_zapier_data', $zapierData );
$response = wp_remote_post( $newLeadHookUrl, array(
'method' => 'POST',
'timeout' => 10,
'headers' => array(
'Content-Type' => 'application/json',
'Accept' => 'application/json'
),
'body' => json_encode($zapierData)
));
}
public static function setTempData( $lead, $temp ) {
global $wpdb;
$sql = $wpdb->prepare("
UPDATE {$wpdb->prefix}opanda_leads
SET lead_temp = %s WHERE ID = %d
", json_encode($temp), $lead->ID );
$wpdb->query($sql);
}
private static $_leads = array();
/**
* Returns a lead.
*/
public static function get( $leadId ) {
if ( isset( self::$_leads[$leadId] ) ) return self::$_leads[$leadId];
global $wpdb;
$lead = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}opanda_leads WHERE ID = %d", $leadId ) );
self::$_leads[$leadId] = $lead;
return $lead;
}
/**
* Returns custom fields
*/
public static function getCustomFields( $leadId = null ) {
if ( !empty( $leadId )) {
global $wpdb;
$data = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}opanda_leads_fields WHERE lead_id = %d AND field_custom = 1", $leadId ), ARRAY_A );
$customFields = array();
foreach( $data as $item ) {
$name = $item['field_name'];
if ( strpos( $name, '_' ) === 0 ) continue;
$customFields[$item['field_name']] = $item['field_value'];
$fields[$name] = strip_tags( $item['field_value'] );
}
return $customFields;
} else {
global $wpdb;
$fields = $wpdb->get_results( "SELECT field_name FROM {$wpdb->prefix}opanda_leads_fields WHERE field_custom = 1 GROUP BY field_name" );
return $fields;
}
}
private static $_fields = array();
/**
* Returns all fields of a given lead.
*
* @since 1.0.7
* @param int $leadId An id of a lead which contains fields to return.
* @return string[]
*/
public static function getLeadFields( $leadId ) {
if ( isset( self::$_fields[$leadId] ) ) return self::$_fields[$leadId];
global $wpdb;
$data = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}opanda_leads_fields WHERE lead_id = %d", $leadId ), ARRAY_A );
$fields = array();
foreach( $data as $item ) {
$fields[$item['field_name']] = $item['field_value'];
}
self::$_fields[$leadId] = $fields;
return $fields;
}
/**
* Returns a given field of a lead.
*
* @since 1.0.7
* @param int $leadId An id of a lead which contains fields to return.
* @param string $fieldName A field name to return.
* @param mixed $default A default value to return if the field is not found in the database.
* @return string
*/
public static function getLeadField( $leadId, $fieldName, $default = null ) {
$fields = self::getLeadFields( $leadId );
return isset( $fields[$fieldName] ) ? $fields[$fieldName] : $default;
}
/**
* Removes a field of a given lead.
*
* @since 1.0.7
* @param int $leadId An id of a lead which contains a field to remove.
* @param string $fieldName A field name to remove.
* @return void
*/
public static function removeLeadField( $leadId, $fieldName ) {
self::updateLeadField( $leadId, $fieldName, null );
}
/**
* Updates a field of a given lead.
*
* @since 1.0.7
* @param int $leadId An id of a lead which contains a field to update.
* @param string $fieldName A field name to update.
* @param string $fieldValue A field value to set.
* @return void
*/
public static function updateLeadField( $leadId, $fieldName, $fieldValue ) {
global $wpdb;
if ( !isset( self::$_fields[$leadId] ) ) {
self::$_fields[$leadId] = self::getLeadFields( $leadId );
}
if ( empty( $fieldValue ) ) {
$wpdb->query( $wpdb->prepare("
DELETE FROM {$wpdb->prefix}opanda_leads_fields
WHERE lead_id = %d AND field_name = %s
", $leadId, $fieldName ));
unset( self::$_fields[$leadId][$fieldName] );
return;
}
$wpdb->query( $wpdb->prepare("
INSERT INTO {$wpdb->prefix}opanda_leads_fields
( lead_id, field_name, field_value )
VALUES ( %d, %s, %s )
ON DUPLICATE KEY UPDATE
field_value = VALUES(field_value)
", $leadId, $fieldName, $fieldValue ));
self::$_fields[$leadId][$fieldName] = $fieldValue;
}
/**
* Return an URL of the image to use as an avatar.
*
* @since 1.0.7
* @param int $leadId A lead ID for which we need to return the URL of the avatar.
* @param int $size A size of the avatar (px).
* @return string
*/
public static function getAvatarUrl( $leadId, $email = null, $size = 40 ) {
$imageSource = OPanda_Leads::getLeadField( $leadId, 'externalImage', null );
$image = OPanda_Leads::getLeadField( $leadId, '_image' . $size, null );
// getting an avatar from cache
if ( !empty( $image ) ) {
$upload_dir = wp_upload_dir();
$path = $upload_dir['path'] . '/bizpanda/avatars/' . $image;
$url = $upload_dir['url'] . '/bizpanda/avatars/' . $image;
if ( file_exists( $path ) ) return $url;
self::removeLeadField($leadId, '_image' . $size);
}
// trying to process an external image
if ( !empty( $imageSource ) && function_exists('wp_get_image_editor') ) {
return admin_url('admin-ajax.php?action=opanda_avatar&opanda_lead_id=' . $leadId) . '&opanda_size=' . $size;
}
// else return a gravatar
$gravatar = get_avatar( $email, $size );
if ( preg_match('/https?\:\/\/[^\'"]+/i', $gravatar, $match) ) {
return $match[0];
}
return null;
}
/**
* Return a HTML code markup to display avatar.
*
* @since 1.0.7
* @param int $leadId A lead ID for which we need to return the URL of the avatar.
* @param int $size A size of the avatar (px).
* @return string HTML
*/
public static function getAvatar( $leadId, $email = null, $size = 40 ) {
$url = self::getAvatarUrl( $leadId, $email, $size );
if ( empty( $url ) ) return null;
$alt = __('User Avatar', 'bizpanda');
return "<img src='$url' width='$size' height='$size' alt='$alt' />";
}
/**
* Returns an URL of the social profile of the lead.
*
* @since 1.0.7
* @param int $leadId A lead ID for which we need to return an URL of the social profile.
* @return string|false An URL of the social profile of the lead.
*/
public static function getSocialUrl( $leadId ) {
$fields = self::getLeadFields( $leadId );
if ( isset( $fields['facebookUrl'] )) return $fields['facebookUrl'];
if ( isset( $fields['twitterUrl'] )) return $fields['twitterUrl'];
if ( isset( $fields['googleUrl'] )) return $fields['googleUrl'];
if ( isset( $fields['linkedinUrl'] )) return $fields['linkedinUrl'];
return false;
}
/**
* Returns the following array:
*
* 'confirmed' => the number of leads (int),
* 'not-fonfirmed' => the number of leads (int)
*
* @since 1.0.7
*/
public static function getCountByStatus() {
global $wpdb;
$rows = $wpdb->get_results(
"SELECT COUNT(*) as status_count, lead_email_confirmed FROM {$wpdb->prefix}opanda_leads GROUP BY lead_email_confirmed",
ARRAY_A
);
$result = array();
foreach( $rows as $row ) {
$status = $row['lead_email_confirmed'] == 1 ? 'confirmed' : 'not-confirmed';
$result[$status] = intval( $row['status_count'] );
}
if ( !isset( $result['confirmed'] )) $result['confirmed'] = 0;
if ( !isset( $result['not-confirmed'] )) $result['not-confirmed'] = 0;
return $result;
}
/**
* Returns a lead by email or null.
*/
public static function getByEmail( $email ) {
global $wpdb;
return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}opanda_leads WHERE lead_email = %s", $email ));
}
/**
* Returns a lead by ID or null.
*/
public static function getById( $id ) {
global $wpdb;
return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}opanda_leads WHERE ID = %s", $id ));
}
protected static function extract( $name, $source, $default = null ) {
$value = isset( $source[$name] ) ? trim( $source[$name] ) : $default;
if ( empty( $value ) ) $value = $default;
return $value;
}
public static function getCount( $cache = true ) {
global $wpdb;
$count = null;
if ( $cache ) {
$count = get_transient('opanda_subscribers_count');
if ( $count === '0' || !empty( $count ) ) return intval( $count );
}
if( $wpdb->get_var("SHOW TABLES LIKE '{$wpdb->prefix}opanda_leads'") === $wpdb->prefix . 'opanda_leads' ) {
$count = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}opanda_leads" );
set_transient('opanda_subscribers_count', $count, 60 * 5);
}
return $count;
}
public static function updateCount() {
self::getCount( false );
}
public static function getIP( ) {
$ip = '';
foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key){
if ( array_key_exists($key, $_SERVER) !== true) continue;
foreach (explode(',', $_SERVER[$key]) as $ip){
$ip = trim($ip);
if ( !self::validateIP($ip) ) continue;
return $ip;
}
}
return $ip;
}
public static function validateIP($ip) {
if (strtolower($ip) === 'unknown') return false;
// generate ipv4 network address
$ip = ip2long($ip);
// if the ip is set and not equivalent to 255.255.255.255
if ($ip !== false && $ip !== -1) {
// make sure to get unsigned long representation of ip
// due to discrepancies between 32 and 64 bit OSes and
// signed numbers (ints default to signed in PHP)
$ip = sprintf('%u', $ip);
// do private network range checking
if ($ip >= 0 && $ip <= 50331647) return false;
if ($ip >= 167772160 && $ip <= 184549375) return false;
if ($ip >= 2130706432 && $ip <= 2147483647) return false;
if ($ip >= 2851995648 && $ip <= 2852061183) return false;
if ($ip >= 2886729728 && $ip <= 2887778303) return false;
if ($ip >= 3221225984 && $ip <= 3221226239) return false;
if ($ip >= 3232235520 && $ip <= 3232301055) return false;
if ($ip >= 4294967040) return false;
}
return true;
}
}

View File

@@ -0,0 +1,205 @@
<?php
class OPanda_Plugins {
public static function getAll() {
$items = array();
$items[] = array(
'name' => 'optinpanda',
'type' => 'free',
'title' => __('Opt-In Panda', 'bizpanda'),
'description' => __('<p>Get more email subscribers the most organic way without tiresome popups.</p><p>Opt-In Panda locks a portion of content on a webpage behind an attractive opt-in form.</p>', 'opanda'),
'url' => 'https://wordpress.org/plugins/opt-in-panda/',
'tags' => array('social', 'subscribers'),
'pluginName' => 'optinpanda'
);
$items[] = array(
'name' => 'optinpanda',
'type' => 'premium',
'title' => __('Opt-In Panda', 'bizpanda'),
'description' => __('<p>Get more email subscribers the most organic way without tiresome popups.</p><p>Also extends the Sign-In Locker by adding the subscription features.</p>', 'bizpanda'),
'url' => 'http://api.byonepress.com/public/1.0/get/?product=optinpanda',
'tags' => array('social', 'subscribers'),
'pluginName' => 'optinpanda'
);
$items[] = array(
'name' => 'sociallocker',
'type' => 'free',
'title' => __('Social Locker (Plugin)', 'bizpanda'),
'description' => __('<p>Helps to attract social traffic and improve spreading your content in social networks.</p>', 'bizpanda'),
'url' => 'https://wordpress.org/plugins/social-locker/',
'tags' => array('social', 'subscribers', 'sociallocker-ads'),
'pluginName' => 'sociallocker-next'
);
$items[] = array(
'name' => 'sociallocker',
'type' => 'premium',
'title' => __('Social Locker', 'bizpanda'),
'description' => __('<p>Helps to attract social traffic and improve spreading your content in social networks.</p><p>Also extends the Sign-In Locker by adding social actions you can set up to be performed.</p>', 'bizpanda'),
'upgradeToPremium' => __('<p>A premium version of the plugin Social Locker.</p><p>7 Social Buttons, 5 Beautiful Themes, Blurring Effect, Countdown Timer, Close Cross and more!</p>', 'bizpanda'),
'url' => 'http://api.byonepress.com/public/1.0/get/?product=sociallocker-next',
'tags' => array('social', 'subscribers', 'sociallocker-ads'),
'pluginName' => 'sociallocker-next'
);
return $items;
}
public static function getPremium() {
$all = self::getAll();
$premium = array();
foreach( $all as $item ) {
if ( $item['type'] !== 'premium' ) continue;
$premium[] = $item;
}
return $premium;
}
public static function getFree() {
$all = self::getAll();
$free = array();
foreach( $all as $item ) {
if ( $item['type'] !== 'free' ) continue;
$free[] = $item;
}
return $free;
}
public static function getSuggestions() {
$added = array();
$existingTags = array();
$suggestions = array();
// suggests premium version of free plugins
$plugins = BizPanda::getInstalledPlugins();
$hasPremium = false;
foreach( $plugins as $plugin ) {
if ( 'premium' === $plugin['type'] ) $hasPremium = true;
$pluginInfo = self::getPluginInfo($plugin['name'], $plugin['type']);
if ( !empty( $pluginInfo ) && isset( $pluginInfo['tags'] ) ) {
$existingTags = array_merge( $existingTags, $pluginInfo['tags'] );
}
if ( 'free' !== $plugin['type'] ) continue;
$pluginInfo = self::getPluginInfo($plugin['name'], 'premium');
if ( empty( $pluginInfo ) ) continue;
if ( isset( $pluginInfo['upgradeToPremium'] ) ) {
$pluginInfo['description'] = $pluginInfo['upgradeToPremium'];
}
$suggestions[] = $pluginInfo;
$added[] = $plugin['name'];
}
// adds installed plugins
foreach( $plugins as $plugin ) {
if ( in_array( $plugin['name'], $added ) ) continue;
$added[] = $plugin['name'];
}
// suggests other extending plugins
$all = self::getAll();
foreach( $all as $item ) {
if ( $hasPremium && 'premium' !== $item['type'] ) continue;
if ( in_array( $item['name'], $added ) ) continue;
if ( !isset( $item['tags'] ) ) continue;
$intersect = array_intersect( $existingTags, $item['tags'] );
if ( empty( $intersect ) ) continue;
$suggestions[] = $item;
$added[] = $item['name'];
}
$suggestions = apply_filters( 'opanda_plugins_suggestions', $suggestions );
return $suggestions;
}
public static function getPluginInfo( $pluginName, $type = null ) {
$all = self::getAll();
foreach( $all as $item ) {
if ( $item['name'] !== $pluginName ) continue;
if ( !empty( $type ) && $item['type'] !== $type ) continue;
return $item;
}
return false;
}
public static function getFreeInfo( $pluginName ) {
return self::getPluginInfo( $pluginName, 'free' );
}
public static function getPremiumInfo( $pluginName ) {
return self::getPluginInfo( $pluginName, 'premium' );
}
public static function getUrl( $pluginName, $type = null, $campaing = null ) {
$pluginInfo = self::getPluginInfo( $pluginName, $type );
if ( empty( $pluginInfo ) ) return $pluginInfo;
$url = $pluginInfo['url'];
if ( empty( $campaing ) ) return $url;
if ( false === strpos( $url, 'utm_source') ) {
if ( BizPanda::isSinglePlugin() ) {
$plugin = BizPanda::getPlugin();
$args = array(
'utm_source' => 'plugin-' . $plugin->options['name'],
'utm_medium' => ( $plugin->license && isset( $plugin->license->data['Category'] ) )
? ( $plugin->license->data['Category'] . '-version' )
: 'unknown-version',
'utm_campaign' => $campaing,
'tracker' => isset( $plugin->options['tracker'] ) ? $plugin->options['tracker'] : null
);
$url = add_query_arg( $args, $url );
} else {
$url = add_query_arg( array(
'utm_source' => 'plugin-bizpanda',
'utm_medium' => 'mixed-versions',
'utm_campaign' => $campaing,
'utm_term' => implode(',', BizPanda::getPluginNames( true ) )
), $url );
}
}
return $url;
}
public static function getPremiumUrl( $pluginName, $campaing = null ) {
return self::getUrl( $pluginName, 'premium', $campaing );
}
public static function getFreeUrl( $pluginName, $campaing = null ) {
return self::getUrl( $pluginName, 'free', $campaing );
}
}

View File

@@ -0,0 +1,307 @@
<?php
class OPanda_Stats {
/**
* Returns data to show charts.
*
* Charts show the stats for a specified item and for all or a single posts.
* @return mixed[]
*/
public static function getChartData( $options ) {
global $wpdb;
$postId = isset( $options['postId'] ) ? $options['postId'] : null;
$itemId = isset( $options['itemId'] ) ? $options['itemId'] : null;
$rangeStart = isset( $options['rangeStart'] ) ? $options['rangeStart'] : null;
$rangeEnd = isset( $options['rangeEnd'] ) ? $options['rangeEnd'] : null;
$rangeStartStr = gmdate("Y-m-d", $rangeStart);
$rangeEndStr = gmdate("Y-m-d", $rangeEnd);
// building and executeing a sql query
$extraWhere = '';
if ($postId) $extraWhere .= ' AND t.post_id=' . $postId;
if ($itemId) $extraWhere .= ' AND t.item_id=' . $itemId;
$sql = "SELECT
t.aggregate_date AS aggregate_date,
t.metric_name AS metric_name,
SUM(t.metric_value) AS metric_value
FROM
{$wpdb->prefix}opanda_stats_v2 AS t
WHERE
(aggregate_date BETWEEN '$rangeStartStr' AND '$rangeEndStr')
$extraWhere
GROUP BY
t.aggregate_date, t.metric_name";
$rawData = $wpdb->get_results($sql, ARRAY_A);
// extracting metric names stored in the database &
// grouping the same metrics data per day
$metricNames = array();
$data = array();
foreach( $rawData as $row ) {
$metricName = $row['metric_name'];
$metricValue = $row['metric_value'];
if ( !in_array( $metricName, $metricNames ) ) $metricNames[] = $metricName;
$timestamp = strtotime( $row['aggregate_date'] );
$data[$timestamp][$metricName] = $metricValue;
}
// normalizing data by adding zero value for skipped dates
$resultData = array();
$currentDate = $rangeStart;
while($currentDate <= $rangeEnd) {
$phpdate = getdate($currentDate);
$resultData[$currentDate] = array();
$resultData[$currentDate]['day'] = $phpdate['mday'];
$resultData[$currentDate]['mon'] = $phpdate['mon'] - 1;
$resultData[$currentDate]['year'] = $phpdate['year'];
$resultData[$currentDate]['timestamp'] = $currentDate;
foreach ($metricNames as $metricName) {
if ( !isset( $data[$currentDate][$metricName] ) )
$resultData[$currentDate][$metricName] = 0;
else
$resultData[$currentDate][$metricName] = $data[$currentDate][$metricName];
}
$currentDate = strtotime("+1 days", $currentDate);
}
return $resultData;
}
/**
* Returns data to show in the data table.
*/
public static function getViewTable( $options ) {
global $wpdb;
$per = isset( $options['per'] ) ? $options['per'] : 50;
$page = isset( $options['page'] ) ? $options['page'] : 1;
$total = isset( $options['total'] ) ? $options['total'] : true;
$order = isset( $options['order'] ) ? $options['order'] : 'unlock';
$rangeStart = isset( $options['rangeStart'] ) ? $options['rangeStart'] : null;
$rangeEnd = isset( $options['rangeEnd'] ) ? $options['rangeEnd'] : null;
$postId = isset( $options['postId'] ) ? $options['postId'] : null;
$itemId = isset( $options['itemId'] ) ? $options['itemId'] : null;
$rangeStartStr = gmdate("Y-m-d", $rangeStart);
$rangeEndStr = gmdate("Y-m-d", $rangeEnd);
$start = ( $page - 1 ) * $per;
$extraWhere = '';
if ($postId) $extraWhere .= 'AND t.post_id=' . $postId;
if ($itemId) $extraWhere .= ' AND t.item_id=' . $itemId;
$count = ( $total ) ? $wpdb->get_var(
"SELECT COUNT(Distinct t.post_id) FROM {$wpdb->prefix}opanda_stats_v2 AS t
WHERE (aggregate_date BETWEEN '$rangeStartStr' AND '$rangeEndStr') $extraWhere") : 0;
$sql = "
SELECT
t.metric_name AS metric_name,
SUM(t.metric_value) AS metric_value,
t.post_id AS post_id,
p.post_title AS post_title
FROM
{$wpdb->prefix}opanda_stats_v2 AS t
LEFT JOIN
{$wpdb->prefix}posts AS p ON p.ID = t.post_id
WHERE
(aggregate_date BETWEEN '$rangeStartStr' AND '$rangeEndStr') $extraWhere
GROUP BY t.post_id, t.metric_name";
$rawData = $wpdb->get_results($sql, ARRAY_A);
// extracting metric names stored in the database &
// grouping the same metrics data per day
$metricNames = array();
$resultData = array();
foreach( $rawData as $row ) {
$metricName = $row['metric_name'];
$metricValue = $row['metric_value'];
$postId = $row['post_id'];
if ( !in_array( $metricName, $metricNames ) ) $metricNames[] = $metricName;
if ( !isset( $resultData[$postId] ) ) {
$title = $row['post_title'];
if ( empty( $title ) ) $title = __('(the post not found)', 'bizpanda');
$resultData[$postId]['id'] = $postId;
$resultData[$postId]['title'] = $title;
}
$resultData[$postId][$metricName] = $metricValue;
}
$returnData = array();
foreach( $resultData as $row ) {
$returnData[] = $row;
}
return array(
'data' => $returnData,
'count' => $count
);
}
private static $_currentMySqlDate = null;
/**
* A helper method to return a current date in the MySQL format.
*/
public static function getCurrentMySqlDate() {
if ( self::$_currentMySqlDate ) return self::$_currentMySqlDate;
$hrsOffset = get_option('gmt_offset');
if (strpos($hrsOffset, '-') !== 0) $hrsOffset = '+' . $hrsOffset;
$hrsOffset .= ' hours';
$time = strtotime($hrsOffset, time());
self::$_currentMySqlDate = date("Y-m-d", $time);
return self::$_currentMySqlDate;
}
/**
* Counts custom metric.
*/
public static function countMetrict( $itemId, $postId, $metricName ) {
global $wpdb;
if ( empty( $itemId ) || empty( $postId ) ) return;
$sql = $wpdb->prepare(
"INSERT INTO {$wpdb->prefix}opanda_stats_v2
(aggregate_date,item_id,post_id,metric_name,metric_value)
VALUES (%s,%d,%d,%s,1)
ON DUPLICATE KEY UPDATE metric_value = metric_value + 1",
self::getCurrentMySqlDate(), $itemId, $postId, $metricName
);
$wpdb->query($sql);
}
/**
* Counts an event (unlock, impress, etc.)
*/
public static function processEvent( $itemId, $postId, $eventName, $eventType ) {
if ( 'unlock' == $eventType ) {
self::countMetrict( $itemId, $postId, 'unlock' );
self::countMetrict( $itemId, $postId, 'unlock-via-' . $eventName );
$post = get_post( $postId );
$locker = get_post( $itemId );
if ( get_option('opanda_notify_unlocks', false) ) {
$receiver = trim ( get_option('opanda_unlocks_email_receiver') );
$subject = trim ( get_option('opanda_unlocks_email_subject') );
$message = trim ( get_option('opanda_unlocks_email_body') );
$context = array(
sprintf ( __( 'Locker: %s', 'bizpanda' ), $locker->post_title ),
sprintf ( __( 'Via: %s', 'bizpanda' ), ucwords( str_replace( '-', ' ', $eventName ) ) ),
sprintf ( __( 'Where: <a href="%s">%s</a>', 'bizpanda' ), get_permalink( $postId ), $post->post_title ),
sprintf ( __( 'IP: %s', 'bizpanda' ), OPanda_Leads::getIP() )
);
$context = apply_filters('opanda_unlock_notification_context', $context);
$replacements = array(
'sitename' => get_bloginfo('name'),
'siteurl' => get_bloginfo('url'),
'context' => implode('<br />', $context)
);
foreach( $replacements as $name => $replacement ) {
$subject = str_replace('{'. $name . '}', $replacement, $subject);
$message = str_replace('{'. $name . '}', $replacement, $message);
}
$headers = array();
$headers[] = 'content-type: text/html';
$subject = apply_filters('opanda_unlocks_notification_subject', $subject, $data );
$message = apply_filters('opanda_unlocks_notification_message', $message, $data );
wp_mail( $receiver, $subject, $message, $headers );
}
self::pushUnlockToZapier(array(
'locker' => $locker->post_title,
'via' => ucwords( str_replace( '-', ' ', $eventName ) ),
'post_title' => $post->post_title,
'post_url' => get_permalink( $postId ),
'ip' => OPanda_Leads::getIP()
));
} elseif ( 'skip' == $eventType ) {
self::countMetrict( $itemId, $postId, 'skip' );
self::countMetrict( $itemId, $postId, 'skip-via-' . $eventName );
} else {
self::countMetrict( $itemId, $postId, $eventName );
}
// updates the summary stats for the item
if ( 'unlock' === $eventType ) {
$unlocks = intval( get_post_meta($itemId, 'opanda_unlocks', true) );
$unlocks++;
update_post_meta($itemId, 'opanda_unlocks', $unlocks);
} elseif ( 'impress' === $eventName ) {
$imperessions = intval( get_post_meta($itemId, 'opanda_imperessions', true) );
$imperessions++;
update_post_meta($itemId, 'opanda_imperessions', $imperessions);
}
}
/**
* Sends unlock data to Zapier.
*/
public static function pushUnlockToZapier( $zapierData = array() ) {
global $wpdb;
$newUnlockHookUrl = trim( get_option('opanda_zipier_hook_new_unlocks', "" ) );
if ( empty( $newUnlockHookUrl ) ) return;
$zapierData = apply_filters('opanda_zapier_data', $zapierData );
$response = wp_remote_post( $newUnlockHookUrl, array(
'method' => 'POST',
'timeout' => 5,
'headers' => array(
'Content-Type' => 'application/json',
'Accept' => 'application/json'
),
'body' => json_encode($zapierData)
));
}
}

View File

@@ -0,0 +1,184 @@
<?php
class OPanda_SubscriptionServices {
/**
* Returns a list of available subscription services.
*
* @since 1.0.8
* @return mixed[]
*/
public static function getSerivcesList() {
$result = apply_filters('opanda_subscription_services', array() );
$helper = array();
foreach( $result as $name => $data ) {
$helper[$name] = $data['title'];
}
array_multisort( $result, $helper );
return $result;
}
/**
* Returns a name of the current subscription service.
*
* @since 1.0.8
* @return OPanda_Subscription
*/
public static function getCurrentName() {
return get_option('opanda_subscription_service', 'none');
}
/**
* Returns a title of the current subscription service.
*
* @since 1.0.8
* @return OPanda_Subscription
*/
public static function getCurrentServiceTitle() {
$info = self::getCurrentServiceInfo();
return !empty( $info ) ? $info['title'] : null;
}
/**
* Returns information about the current subscription service.
*
* @since 1.0.8
* @return string[]
*/
public static function getCurrentServiceInfo() {
return self::getServiceInfo( null );
}
/**
* Returns an object of the current subscription service.
*
* @since 1.0.8
* @return OPanda_Subscription
*/
public static function getCurrentService() {
return self::getService( null );
}
/**
* Returns information about a specified service.
*
* @since 1.0.8
* @param string $name A name of the service to return.
* @return mixed[]
*/
public static function getServiceInfo( $name = null ) {
$services = self::getSerivcesList();
$name = empty( $name ) ? get_option('opanda_subscription_service', 'none') : $name;
if ( !isset( $services[$name] ) ) $name = 'none';
if ( isset( $services[$name] ) ) {
$services[$name]['name'] = $name;
return $services[$name];
}
return null;
}
/**
* Returns an object of a specified subscription service.
*
* @since 1.0.8
* @param string $name A name of the service to return.
* @return OPanda_Subscription
*/
public static function getService( $name = null ) {
require_once OPANDA_BIZPANDA_DIR . '/admin/includes/classes/class.subscription.php';
$info = self::getServiceInfo( $name );
if ( empty( $info) ) return null;
require_once $info['path'];
return new $info['class']( $info );
}
/**
* Returns available opt-in modes for the current subscription service.
*
* @since 1.0.8
* @param string $name A name of the service to return.
* @return mixed[]
*/
public static function getCurrentOptinModes( $toList = false ) {
$result = array();
$finish = array();
$info = self::getCurrentServiceInfo();
if ( empty( $info ) ) return array();
if ( OPANDA_DEPENDS_ON_LIST === $info['modes'] ) {
if ( !$toList ) {
return array( OPANDA_DEPENDS_ON_LIST );
} else {
$finish[] = array( OPANDA_DEPENDS_ON_LIST, __('[ Depends on the list ]', 'bizpanda'), __( 'The Opt-In Mode depends on the settings of the list you selected. Check the <a href="http://freshmail.com/help-and-knowledge/help/managing-clients/set-parameters-list-recipients/" target="_blank">parameter</a> "List type" of the selected list in your FreshMail account to know which Opt-In Mode will be applied.', 'bizpanda') );
return $finish;
}
}
$all = self::getAllOptinModes();
foreach( $info['modes'] as $name ) {
$result[$name] = $all[$name];
}
if ( !$toList ) return $result;
if ( isset( $result['quick'] ) ) {
if ( !isset($result['double-optin'] ) ) {
$result['double-optin'] = $all['double-optin'];
}
if ( !isset($result['quick-double-optin'] ) ) {
$result['quick-double-optin'] = $all['quick-double-optin'];
}
}
foreach( $result as $name => $mode ) {
$finish[] = array(
'value' => $name,
'title' => $mode['title'],
'hint' => $mode['description']
);
}
return $finish;
}
/**
* Returns all the available opt-in modes.
*
* @since 1.0.8
* @return mixed[]
*/
public static function getAllOptinModes() {
$modes = array(
'double-optin' => array(
'title' => __('Double Opt-In', 'bizpanda'),
'description' => __('After the user enters one\'s email address, sends the confirmation email (double opt-in) and waits until the user confirms the subscription. Then, unlocks the content. If the user subscribes via the social buttons, the confirmation is not required.', 'bizpanda')
),
'quick-double-optin' => array(
'title' => __('Lazy Double Opt-In', 'bizpanda'),
'description' => __('Unlocks the content immediately after the user enters one\'s email address but also sends the confirmation email (double opt-in) to confirm the subscription. If the user subscribes via the social buttons, the confirmation is not required.', 'bizpanda')
),
'quick' => array(
'title' => __('Single Opt-In', 'bizpanda'),
'description' => __('Unlocks the content immediately after the user enters one\'s email address. Doesn\'t send the confirmation email.', 'bizpanda')
),
);
return apply_filters('opanda_optin_modes', $modes);
}
}

View File

@@ -0,0 +1,137 @@
<?php
class OPanda_ItemsViewTable extends FactoryViewtables320_Viewtable
{
public function configure()
{
/**
* Columns
*/
$this->columns->clear();
$this->columns->add('stats', __('<span title="Unlocks / Impressions / Conversion">U / I / %', 'bizpanda'));
$this->columns->add('title', __('Locker Title', 'bizpanda'));
$this->columns->add('shortcode', __('Shortcode', 'bizpanda'));
$this->columns->add('bulk', __('Bulk Lock', 'bizpanda'));
$this->columns->add('visibility', __('Visibility', 'bizpanda'));
$this->columns->add('created', __('Created', 'bizpanda'));
/**
* Scripts & styles
*/
$this->scripts->add(OPANDA_BIZPANDA_URL . '/assets/admin/js/item-view.010000.js');
$this->styles->add(OPANDA_BIZPANDA_URL . '/assets//admin/css/item-view.010000.css');
}
/**
* Column 'Title'
*/
public function columnTitle( $post, $isFullMode ) {
if ($isFullMode ) {
$url = get_post_meta($post->ID, 'opanda_theme', true);
if ( empty($url) ) $url = '<i>[current page]</i>';
echo '<p>' . $post->post_title . '</p>';
echo '<p>' . $url . '</p>';
} else {
echo $post->post_title;
}
}
/**
* Column 'Shortcode'
*/
public function columnShortcode( $post, $isFullMode ) {
$isSystem = get_post_meta( $post->ID, 'opanda_is_system', true);
$itemTypeName = get_post_meta( $post->ID, 'opanda_item', true);
$item = OPanda_Items::getItem( $itemTypeName );
$shortcodeName = $item['shortcode'];
$shortcode = '[' . $shortcodeName . '] [/' . $shortcodeName . ']';
if (!$isSystem) $shortcode = '[' . $shortcodeName . ' id="' . $post->ID . '"] [/' . $shortcodeName . ']';
?>
<input class="shortcode" type="text" value='<?php echo $shortcode ?>' />
<?php
}
/**
* Column 'Shortcode'
*/
public function columnBulk( $post, $isFullMode ) {
?>
<div class='onp-sl-inner-wrap'>
<?php echo opanda_print_bulk_locking_state( $post->ID ); ?>
</div>
<?php
}
/**
* Column 'Theme'
*/
public function columnVisibility( $post, $isFullMode ) {
$theme = get_post_meta($post->ID, 'opanda_style', true);
echo $theme;
}
/**
* Column 'Created'
*/
public function columnCreated( $post, $isFullMode ) {
$t_time = get_the_time( 'Y/m/d g:i:s A' );
$m_time = $post->post_date;
$time = get_post_time( 'G', true, $post );
$time_diff = time() - $time;
if ( $time_diff > 0 && $time_diff < 24*60*60 )
$h_time = sprintf( '%s ago', human_time_diff( $time ) );
else
$h_time = mysql2date( 'Y/m/d', $m_time );
echo '<abbr title="' . esc_attr( $t_time ) . '">' . $h_time . '</abbr><br />';
}
/**
* Column 'Created'
*/
public function columnStats( $post ) {
global $optinpanda;
$imperessions = intval( get_post_meta($post->ID, 'opanda_imperessions', true) );
$conversion = '0';
$unlocks = intval( get_post_meta($post->ID, 'opanda_unlocks', true) );
if ( !empty( $imperessions )) {
$conversion = round( $unlocks / $imperessions * 100, 2 );
} elseif ( !empty( $unlocks ) ) {
$conversion = 100;
}
$strong = ( $unlocks > 0 );
$url = opanda_get_admin_url('stats', array('opanda_id' => $post->ID));
if ( $strong ) {
echo '<a href="' . $url . '"><strong>' . $unlocks . '</strong> / ' . $imperessions . ' / ' . sprintf( '%.02f', $conversion ) . '%' . '</a>';
} else {
echo '<a href="' . $url . '" class="opanda-empty">' . $unlocks . ' / ' . $imperessions . ' / ' . sprintf( '%.02f', $conversion ) . '%' . '</a>';
}
?>
<?php
}
}