Files
old-experiments/backend/wordpress/wp-content/plugins/gravityflow-master/includes/assignees/class-assignee.php
2018-06-29 14:40:28 +02:00

554 lines
13 KiB
PHP
Executable File

<?php
/**
* Gravity Flow Assignee
*
* @package GravityFlow
* @subpackage Classes/Assignee
* @copyright Copyright (c) 2015-2018, Steven Henty S.L.
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.0
*/
if ( ! class_exists( 'GFForms' ) ) {
die();
}
/**
* Class Gravity_Flow_Assignee
*/
class Gravity_Flow_Assignee {
/**
* The unique name of this assignee.
*
* @since 2.1
*
* @var string
*/
public $name = 'generic';
/**
* The ID of this assignee.
*
* @since 1.0
*
* @var string
*/
protected $id;
/* @var string The Type of this assignee */
/**
* The Type of this assignee.
*
* @since 1.0
*
* @var string
*/
protected $type;
/**
* The Assignee key.
*
* @since 1.0
*
* @var string
*/
protected $key;
/**
* The editable fields for this assignee.
*
* @since 1.0
*
* @var array
*/
protected $editable_fields = array();
/**
* The WordPress user account for this assignee
*
* @since 1.7.1
*
* @var WP_User
*/
protected $user = null;
/**
* The step.
*
* @since 1.0
*
* @var Gravity_Flow_Step|bool
*/
protected $step;
/**
* Gravity_Flow_Assignee constructor.
*
* @since 1.0
*
* @param string|array $args An assignee key or array.
* @param bool|Gravity_Flow_Step $step The current step or false.
*/
public function __construct( $args = array(), $step = false ) {
if ( empty( $args ) ) {
return;
}
$this->step = $step;
if ( is_string( $args ) ) {
$parts = explode( '|', $args );
$type = $parts[0];
$id = $parts[1];
} elseif ( is_array( $args ) ) {
$id = $args['id'];
$type = $args['type'];
if ( isset( $args['editable_fields'] ) ) {
$this->editable_fields = $args['editable_fields'];
}
if ( isset( $args['user'] ) && $args['user'] instanceof WP_User ) {
$this->user = $args['user'];
}
} else {
return;
}
switch ( $type ) {
case 'assignee_field':
$entry = $this->step->get_entry();
$assignee_key = rgar( $entry, $id );
list( $this->type, $this->id ) = rgexplode( '|', $assignee_key, 2 );
break;
case 'assignee_user_field':
$entry = $this->step->get_entry();
$this->id = absint( rgar( $entry, $id ) );
$this->type = 'user_id';
break;
case 'assignee_role_field':
$entry = $this->step->get_entry();
$this->id = sanitize_text_field( rgar( $entry, $id ) );
$this->type = 'role';
break;
case 'email_field':
$entry = $this->step->get_entry();
$this->id = sanitize_email( rgar( $entry, $id ) );
$this->type = 'email';
break;
case 'entry':
$entry = $this->step->get_entry();
$this->id = rgar( $entry, $id );
$this->type = 'user_id';
break;
default:
$this->type = $type;
$this->id = $id;
}
$this->maybe_set_user();
$this->key = $this->type . '|' . $this->id;
}
/**
* If applicable, set the user property for the assignee.
*
* @since 1.7.1
*/
protected function maybe_set_user() {
if ( ! $this->get_user() ) {
if ( $this->get_type() === 'user_id' ) {
$user = get_user_by( 'ID', $this->get_id() );
} elseif ( $this->get_type() === 'email' ) {
$user = get_user_by( 'email', $this->get_id() );
} else {
$user = false;
}
if ( $user ) {
$this->user = $user;
}
}
}
/**
* Return the assignee ID.
*
* @return string
*/
public function get_id() {
return $this->id;
}
/**
* Return the assignee key.
*
* @return string
*/
public function get_key() {
return $this->key;
}
/**
* Return the assignee type.
*
* @return string
*/
public function get_type() {
return $this->type;
}
/**
* Return the editable field IDs for this assignee.
*
* @return array
*/
public function get_editable_fields() {
return $this->editable_fields;
}
/**
* Returns the user account for this assignee.
*
* @since 1.7.1
*
* @return WP_User
*/
public function get_user() {
return $this->user;
}
/**
* Returns the status.
*
* @return bool|mixed
*/
public function get_status() {
$entry_id = $this->step->get_entry_id();
$key = $this->get_status_key();
$cache_key = gravity_flow()->is_gravityforms_supported( '2.3-beta-3' ) ? get_current_blog_id() . '_' : '';
$cache_key .= $entry_id . '_' . $key;
global $_gform_lead_meta;
unset( $_gform_lead_meta[ $cache_key ] );
return gform_get_meta( $entry_id, $key );
}
/**
* Returns the status key.
*
* @return string
*/
public function get_status_key() {
$assignee_id = $this->get_id();
$assignee_type = $this->get_type();
$key = 'workflow_' . $assignee_type . '_' . $assignee_id;
return $key;
}
/**
* Update the status entry meta items for this assignee.
*
* @param string|bool $new_assignee_status The new status for this assignee or false.
*/
public function update_status( $new_assignee_status = false ) {
$key = $this->get_status_key();
$assignee_status_timestamp = gform_get_meta( $this->step->get_entry_id(), $key . '_timestamp' );
$duration = $assignee_status_timestamp ? time() - $assignee_status_timestamp : 0;
gform_update_meta( $this->step->get_entry_id(), $key, $new_assignee_status );
gform_update_meta( $this->step->get_entry_id(), $key . '_timestamp', time() );
$this->log_event( $new_assignee_status, $duration );
}
/**
* Return the assignee display name.
*
* @return string
*/
public function get_display_name() {
$user = $this->get_user();
$name = $user ? $user->display_name : $this->get_id();
return $name;
}
/**
* Remove the assignee from the current step by deleting the associated entry meta items.
*/
public function remove() {
$key = $this->get_status_key();
gform_delete_meta( $this->step->get_entry_id(), $key );
gform_delete_meta( $this->step->get_entry_id(), $key . '_timestamp' );
$reminder_timestamp_key = $key . '_reminder_timestamp';
gform_delete_meta( $this->step->get_entry_id(), $reminder_timestamp_key );
}
/**
* Returns the status timestamp.
*
* @return bool|mixed
*/
public function get_status_timestamp() {
$status_key = $this->get_status_key();
$timestamp_key = $status_key . '_timestamp';
return gform_get_meta( $this->step->get_entry_id(), $timestamp_key );
}
/**
* Returns the status timestamp.
*
* @return bool|mixed
*/
public function get_reminder_timestamp() {
$status_key = $this->get_status_key();
$timestamp_key = $status_key . '_reminder_timestamp';
return gform_get_meta( $this->step->get_entry_id(), $timestamp_key );
}
/**
* Sets the timestamp for the reminder.
*
* @param bool|int $timestamp Unix GMT timestamp or false.
*/
public function set_reminder_timestamp( $timestamp = false ) {
if ( empty( $timestamp ) ) {
$timestamp = time();
}
$status_key = $this->get_status_key();
$timestamp_key = $status_key . '_reminder_timestamp';
gform_update_meta( $this->step->get_entry_id(), $timestamp_key, $timestamp );
}
/**
* Log an event for the current assignee.
*
* @param string $status The assignee status.
* @param int $duration Time interval in seconds, if any.
*/
public function log_event( $status, $duration = 0 ) {
gravity_flow()->log_event( 'assignee', 'status', $this->step->get_form_id(), $this->step->get_entry_id(), $status, $this->step->get_id(), $duration, $this->get_id(), $this->get_type(), $this->get_display_name() );
}
/**
* Sends a notification to the assignee.
*
* @uses Gravity_Flow_Step::send_notification() to send, log and deduplicate the notifications.
*
* @since 2.1
*
* @param array $notification The notification to be sent.
*/
public function send_notification( $notification ) {
$message = $notification['message'];
$assignee_type = $this->get_type();
$assignee_id = $this->get_id();
if ( $assignee_type == 'email' ) {
$email = $assignee_id;
$notification['id'] = 'workflow_step_' . $this->get_id() . '_email_' . $email;
$notification['name'] = $notification['id'];
$notification['to'] = $email;
$message = $this->replace_variables( $message );
// Call $this->step->replace_variables() for backwards compatibility
$notification['message'] = $this->step->replace_variables( $message, $this );
$this->step->send_notification( $notification );
return;
}
if ( $assignee_type == 'role' ) {
$users = get_users( array( 'role' => $assignee_id ) );
} else {
$users = get_users( array( 'include' => array( $assignee_id ) ) );
}
$this->step->log_debug( __METHOD__ . sprintf( '() sending notifications to %d users', count( $users ) ) );
$user_assignee_args = array(
'type' => $assignee_type,
'id' => $assignee_id,
);
foreach ( $users as $user ) {
$user_assignee_args['user'] = $user;
$user_assignee = Gravity_Flow_Assignees::create( $user_assignee_args, $this->step );
$notification['id'] = 'workflow_step_' . $this->get_id() . '_user_' . $user->ID;
$notification['name'] = $notification['id'];
$notification['to'] = $user->user_email;
$message = $user_assignee->replace_variables( $message );
// Call $this->step->replace_variables() for backwards compatibility
$notification['message'] = $this->step->replace_variables( $message, $user_assignee );
$this->step->send_notification( $notification );
}
}
/**
* Checks whether the current user (WP or Token auth) is an assignee.
*
* @since 2.1
*
* @return bool
*/
public function is_current_user() {
$current_user_assignee_key = $this->step->get_current_assignee_key();
$current_user_assignee = $this->step->get_assignee( $current_user_assignee_key );
$type = $this->get_type();
if ( ! $current_user_assignee ) {
return false;
}
$status = $this->get_status();
if ( $status != 'pending' ) {
return false;
}
if ( in_array( $type, array( 'user_id', 'email', 'role' ) ) && $current_user_assignee->get_id() == $this->get_id() ) {
return true;
}
if ( $type == 'role' ) {
$user = wp_get_current_user();
$role = $this->get_id();
if ( in_array( $role, (array) $user->roles ) ) {
return true;
}
}
return false;
}
/**
* Processes the status update for the assignee.
*
* @since 2.1
*
* @param string $new_status The status string e.g. complete, approved, rejected.
*
* @return bool|WP_Error True on success or WP_Error
*/
public function process_status( $new_status ) {
$current_user_status = $this->get_status();
list( $role, $current_role_status ) = $this->step->get_current_role_status();
if ( $current_user_status != 'pending' && $current_role_status != 'pending' ) {
$error = new WP_Error( esc_html__( 'The status could not be changed because this step has already been processed.', 'gravityflow' ) );
return $error;
}
if ( $current_user_status == 'pending' ) {
$this->update_status( $new_status );
}
if ( $current_role_status == 'pending' ) {
$this->step->update_role_status( $role, $new_status );
}
$this->step->refresh_entry();
$success = true;
return $success;
}
/**
* Returns the label to be displayed for the assignee on the workflow detail page.
*
* @since 2.1
*
* @return string
*/
public function get_status_label() {
$assignee_status_label = '';
$user_approval_status = $this->get_status();
$this->step->log_debug( __METHOD__ . '(): status for: ' . $this->get_key() );
$this->step->log_debug( __METHOD__ . '(): assignee status: ' . $user_approval_status );
$status_label = $this->step->get_status_label( $user_approval_status );
if ( ! empty( $user_approval_status ) ) {
$assignee_type = $this->get_type();
switch ( $assignee_type ) {
case 'email':
$type_label = esc_html__( 'Email', 'gravityflow' );
$display_name = $this->get_id();
break;
case 'role':
$type_label = esc_html__( 'Role', 'gravityflow' );
$display_name = translate_user_role( $this->get_id() );
break;
case 'user_id':
$user = get_user_by( 'id', $this->get_id() );
$display_name = $user ? $user->display_name : $this->get_id() . ' ' . esc_html__( '(Missing)', 'gravityflow' );
$type_label = esc_html__( 'User', 'gravityflow' );
break;
default:
$display_name = $this->get_id();
$type_label = $this->get_type();
}
$assignee_status_label = sprintf( '%s: %s (%s)', $type_label, $display_name, $status_label );
$assignee_status_label = apply_filters( 'gravityflow_assignee_status_workflow_detail', $assignee_status_label, $this, $this );
}
return $assignee_status_label;
}
/**
* Override this method to replace merge tags.
* Important: call the parent method first.
* $text = parent::replace_variables( $text );
*
* @since 2.1
*
* @param string $text The text containing merge tags to be processed.
*
* @return string
*/
public function replace_variables( $text ) {
$args = array(
'assignee' => $this,
'step' => $this->step,
);
$merge_tags = Gravity_Flow_Merge_Tags::get_all( $args );
foreach ( $merge_tags as $merge_tag ) {
if ( $merge_tag instanceof Gravity_Flow_Merge_Tag_Assignee_Base ) {
$text = $merge_tag->replace( $text );
}
}
return $text;
}
}