コード例 #1
0
ファイル: class-log.php プロジェクト: azanebrain/representme
 /**
  * Log handler
  *
  * @param Connector $connector Connector responsible for logging the event
  * @param string $message      sprintf-ready error message string
  * @param array  $args         sprintf (and extra) arguments to use
  * @param int $object_id       Target object id
  * @param string $context      Context of the event
  * @param string $action       Action of the event
  * @param int $user_id         User responsible for the event
  *
  * @return mixed True if updated, otherwise false|WP_Error
  */
 public function log($connector, $message, $args, $object_id, $context, $action, $user_id = null)
 {
     if (is_null($user_id)) {
         $user_id = get_current_user_id();
     }
     if (is_null($object_id)) {
         $object_id = 0;
     }
     $wp_cron_tracking = isset($this->plugin->settings->options['advanced_wp_cron_tracking']) ? $this->plugin->settings->options['advanced_wp_cron_tracking'] : false;
     $author = new Author($user_id);
     $agent = $author->get_current_agent();
     // WP Cron tracking requires opt-in and WP Cron to be enabled
     if (!$wp_cron_tracking && 'wp_cron' === $agent) {
         return false;
     }
     $user = new \WP_User($user_id);
     if ($this->is_record_excluded($connector, $context, $action, $user)) {
         return false;
     }
     $user_meta = array('user_email' => (string) (!empty($user->user_email)) ? $user->user_email : '', 'display_name' => (string) $author->get_display_name(), 'user_login' => (string) (!empty($user->user_login)) ? $user->user_login : '', 'user_role_label' => (string) $author->get_role(), 'agent' => (string) $agent);
     if ('wp_cli' === $agent && function_exists('posix_getuid')) {
         $uid = posix_getuid();
         $user_info = posix_getpwuid($uid);
         $user_meta['system_user_id'] = (int) $uid;
         $user_meta['system_user_name'] = (string) $user_info['name'];
     }
     // Prevent any meta with null values from being logged
     $stream_meta = array_filter($args, function ($var) {
         return !is_null($var);
     });
     // Add user meta to Stream meta
     $stream_meta['user_meta'] = $user_meta;
     // All meta must be strings, so we will serialize any array meta values
     array_walk($stream_meta, function (&$v) {
         $v = (string) maybe_serialize($v);
     });
     // Get the current time in milliseconds
     $iso_8601_extended_date = wp_stream_get_iso_8601_extended_date();
     $recordarr = array('object_id' => (int) $object_id, 'site_id' => (int) is_multisite() ? get_current_site()->id : 1, 'blog_id' => (int) apply_filters('wp_stream_blog_id_logged', get_current_blog_id()), 'user_id' => (int) $user_id, 'user_role' => (string) (!empty($user->roles)) ? $user->roles[0] : '', 'created' => (string) $iso_8601_extended_date, 'summary' => (string) vsprintf($message, $args), 'connector' => (string) $connector, 'context' => (string) $context, 'action' => (string) $action, 'ip' => (string) wp_stream_filter_input(INPUT_SERVER, 'REMOTE_ADDR', FILTER_VALIDATE_IP), 'meta' => (array) $stream_meta);
     if (0 === $recordarr['object_id']) {
         unset($recordarr['object_id']);
     }
     $result = $this->plugin->db->insert($recordarr);
     $this->debug_backtrace($recordarr);
     return $result;
 }
コード例 #2
0
 /**
  * Get a chunk of records formatted for Stream API ingestion
  *
  * @param  int  $limit  The number of rows to query
  *
  * @return mixed  An array of record arrays, or FALSE if no records were found
  */
 private static function get_records($limit = null)
 {
     $limit = is_int($limit) ? $limit : self::$limit;
     global $wpdb;
     $records = $wpdb->get_results($wpdb->prepare("\n\t\t\t\tSELECT s.*, sc.connector, sc.context, sc.action\n\t\t\t\tFROM {$wpdb->base_prefix}stream AS s, {$wpdb->base_prefix}stream_context AS sc\n\t\t\t\tWHERE s.site_id = %d\n\t\t\t\t\tAND s.blog_id = %d\n\t\t\t\t\tAND s.type = 'stream'\n\t\t\t\t\tAND sc.record_id = s.ID\n\t\t\t\tORDER BY s.created DESC\n\t\t\t\tLIMIT %d\n\t\t\t\t", self::$site_id, self::$blog_id, $limit), ARRAY_A);
     if (empty($records)) {
         return false;
     }
     self::$_records = array();
     foreach ($records as $record => $data) {
         $stream_meta = $wpdb->get_results($wpdb->prepare("SELECT meta_key, meta_value FROM {$wpdb->base_prefix}stream_meta WHERE record_id = %d", $records[$record]['ID']), ARRAY_A);
         $stream_meta_output = array();
         $author_meta_output = array();
         foreach ($stream_meta as $key => $meta) {
             if ('author_meta' === $meta['meta_key'] && !empty($meta['meta_value'])) {
                 $author_meta_output = maybe_unserialize($meta['meta_value']);
                 unset($stream_meta[$key]);
                 continue;
             }
             // Unserialize meta first so we can then check for malformed serialized strings
             $stream_meta_output[$meta['meta_key']] = maybe_unserialize($meta['meta_value']);
             // If any serialized data is still lingering in the meta value that means it's malformed and should be removed
             if (is_string($stream_meta_output[$meta['meta_key']]) && 1 === preg_match('/(a|O) ?\\x3a ?[0-9]+ ?\\x3a ?\\x7b/', $stream_meta_output[$meta['meta_key']])) {
                 unset($stream_meta_output[$meta['meta_key']]);
                 continue;
             }
             // All meta must be strings, so serialize any array meta values again
             $stream_meta_output[$meta['meta_key']] = (string) maybe_serialize($stream_meta_output[$meta['meta_key']]);
         }
         // All author meta must be strings
         array_walk($author_meta_output, function (&$v) {
             $v = (string) $v;
         });
         $records[$record]['stream_meta'] = $stream_meta_output;
         $records[$record]['author_meta'] = $author_meta_output;
         self::$_records[] = $records[$record];
         $records[$record]['created'] = wp_stream_get_iso_8601_extended_date(strtotime($records[$record]['created']));
         unset($records[$record]['ID']);
         unset($records[$record]['parent']);
         // Ensure required fields always exist
         $records[$record]['site_id'] = !empty($records[$record]['site_id']) ? $records[$record]['site_id'] : 1;
         $records[$record]['blog_id'] = !empty($records[$record]['blog_id']) ? $records[$record]['blog_id'] : 1;
         $records[$record]['object_id'] = !empty($records[$record]['object_id']) ? $records[$record]['object_id'] : 0;
         $records[$record]['author'] = !empty($records[$record]['author']) ? $records[$record]['author'] : 0;
         $records[$record]['author_role'] = !empty($records[$record]['author_role']) ? $records[$record]['author_role'] : '';
         $records[$record]['ip'] = !empty($records[$record]['ip']) ? $records[$record]['ip'] : '';
     }
     return $records;
 }
コード例 #3
0
 /**
  * Log handler
  *
  * @param         $connector
  * @param  string $message   sprintf-ready error message string
  * @param  array  $args      sprintf (and extra) arguments to use
  * @param  int    $object_id Target object id
  * @param  string $context   Context of the event
  * @param  string $action    Action of the event
  * @param  int    $user_id   User responsible for the event
  *
  * @return void
  */
 public function log($connector, $message, $args, $object_id, $context, $action, $user_id = null)
 {
     global $wpdb;
     if (is_null($user_id)) {
         $user_id = get_current_user_id();
     }
     if (is_null($object_id)) {
         $object_id = 0;
     }
     $user = new WP_User($user_id);
     $roles = get_option($wpdb->get_blog_prefix() . 'user_roles');
     $visibility = 'publish';
     if (self::is_record_excluded($connector, $context, $action, $user)) {
         $visibility = 'private';
     }
     if (defined('WP_CLI') && empty($user->display_name)) {
         $display_name = 'WP-CLI';
     } elseif (!empty($user->display_name)) {
         $display_name = $user->display_name;
     } else {
         $display_name = '';
     }
     $author_meta = array('user_email' => (string) (!empty($user->user_email)) ? $user->user_email : '', 'display_name' => (string) $display_name, 'user_login' => (string) (!empty($user->user_login)) ? $user->user_login : '', 'user_role_label' => (string) (!empty($user->roles)) ? $roles[$user->roles[0]]['name'] : '', 'agent' => (string) WP_Stream_Author::get_current_agent());
     if (defined('WP_CLI') && function_exists('posix_getuid')) {
         $uid = posix_getuid();
         $user_info = posix_getpwuid($uid);
         $author_meta['system_user_id'] = (int) $uid;
         $author_meta['system_user_name'] = (string) $user_info['name'];
     }
     // Prevent any meta with null values from being logged
     $stream_meta = array_filter($args, function ($var) {
         return !is_null($var);
     });
     // All meta must be strings, so we will serialize any array meta values
     array_walk($stream_meta, function (&$v) {
         $v = (string) maybe_serialize($v);
     });
     // Get the current time in milliseconds
     $iso_8601_extended_date = wp_stream_get_iso_8601_extended_date();
     $recordarr = array('object_id' => (int) $object_id, 'site_id' => (int) is_multisite() ? get_current_site()->id : 1, 'blog_id' => (int) apply_filters('wp_stream_blog_id_logged', is_network_admin() ? 0 : get_current_blog_id()), 'author' => (int) $user_id, 'author_role' => (string) (!empty($user->roles)) ? $user->roles[0] : '', 'author_meta' => (array) $author_meta, 'created' => (string) $iso_8601_extended_date, 'visibility' => (string) $visibility, 'type' => 'stream', 'summary' => (string) vsprintf($message, $args), 'connector' => (string) $connector, 'context' => (string) $context, 'action' => (string) $action, 'stream_meta' => (array) $stream_meta, 'ip' => (string) wp_stream_filter_input(INPUT_SERVER, 'REMOTE_ADDR', FILTER_VALIDATE_IP));
     WP_Stream::$db->store(array($recordarr));
 }
コード例 #4
0
 /**
  * Offsets the record created date by the timezone
  * @return array
  */
 public function offset_record_dates($records)
 {
     $offset = get_option('gmt_offset');
     foreach ($records as $record => $items) {
         foreach ($items as $key => $item) {
             $records[$record][$key]->created = wp_stream_get_iso_8601_extended_date(strtotime($item->created), $offset);
         }
     }
     return $records;
 }
コード例 #5
0
 function column_default($item, $column_name)
 {
     $out = '';
     $record = new Record($item);
     switch ($column_name) {
         case 'date':
             $created = date('Y-m-d H:i:s', strtotime($record->created));
             $date_string = sprintf('<time datetime="%s" class="relative-time record-created">%s</time>', wp_stream_get_iso_8601_extended_date(strtotime($record->created)), get_date_from_gmt($created, 'Y/m/d'));
             $out = $this->column_link($date_string, 'date', get_date_from_gmt($created, 'Y/m/d'));
             $out .= '<br />';
             $out .= get_date_from_gmt($created, 'h:i:s A');
             break;
         case 'summary':
             $out = $record->summary;
             $object_title = $record->get_object_title();
             $view_all_text = $object_title ? sprintf(esc_html__('View all activity for "%s"', 'stream'), esc_attr($object_title)) : esc_html__('View all activity for this object', 'stream');
             if ($record->object_id) {
                 $out .= $this->column_link('<span class="dashicons dashicons-search stream-filter-object-id"></span>', array('object_id' => $record->object_id, 'context' => $record->context), null, esc_attr($view_all_text));
             }
             $out .= $this->get_action_links($record);
             break;
         case 'user_id':
             $user = new Author((int) $record->user_id, (array) maybe_unserialize($record->user_meta));
             $filtered_records_url = add_query_arg(array('page' => $this->plugin->admin->records_page_slug, 'user_id' => absint($user->id)), self_admin_url($this->plugin->admin->admin_parent_page));
             $out = sprintf('<a href="%s">%s <span>%s</span></a>%s%s%s', $filtered_records_url, $user->get_avatar_img(80), $user->get_display_name(), $user->is_deleted() ? sprintf('<br /><small class="deleted">%s</small>', esc_html__('Deleted User', 'stream')) : '', $user->get_role() ? sprintf('<br /><small>%s</small>', $user->get_role()) : '', $user->get_agent() ? sprintf('<br /><small>%s</small>', $user->get_agent_label($user->get_agent())) : '');
             break;
         case 'context':
             $connector_title = $this->get_term_title($record->{'connector'}, 'connector');
             $context_title = $this->get_term_title($record->{'context'}, 'context');
             $out = $this->column_link($connector_title, 'connector', $item->{'connector'});
             $out .= '<br />&#8627;&nbsp;';
             $out .= $this->column_link($context_title, array('connector' => $record->{'connector'}, 'context' => $record->{'context'}));
             break;
         case 'action':
             $out = $this->column_link($this->get_term_title($record->{$column_name}, $column_name), $column_name, $record->{$column_name});
             break;
         case 'blog_id':
             $blog = $record->blog_id && is_multisite() ? get_blog_details($record->blog_id) : $this->plugin->admin->network->get_network_blog();
             $out = $this->column_link($blog->blogname, 'blog_id', $blog->blog_id);
             break;
         case 'ip':
             $out = $this->column_link($record->{$column_name}, 'ip', $record->{$column_name});
             break;
         default:
             /**
              * Registers new Columns to be inserted into the table.  The cell contents of this column is set
              * below with 'wp_stream_inster_column_default-'
              *
              * @return array
              */
             $inserted_columns = apply_filters('wp_stream_register_column_defaults', $new_columns = array());
             if (!empty($inserted_columns) && is_array($inserted_columns)) {
                 foreach ($inserted_columns as $column_title) {
                     /**
                      * If column title inserted via wp_stream_register_column_defaults ($column_title) exists
                      * among columns registered with get_columns ($column_name) and there is an action associated
                      * with this column, do the action
                      *
                      * Also, note that the action name must include the $column_title registered
                      * with wp_stream_register_column_defaults
                      */
                     if ($column_title === $column_name && has_filter("wp_stream_insert_column_default-{$column_title}")) {
                         /**
                          * Allows for the addition of content under a specified column.
                          *
                          * @param object $record  Contents of the row
                          *
                          * @return string
                          */
                         $out = apply_filters("wp_stream_insert_column_default-{$column_title}", $column_name, $record);
                     } else {
                         $out = $column_name;
                     }
                 }
             } else {
                 $out = $column_name;
             }
     }
     echo $out;
     // xss ok
 }
コード例 #6
0
 /**
  * Query Stream records
  *
  * @param array Query args
  *
  * @return array Stream Records
  */
 public function query($args)
 {
     global $wpdb;
     $defaults = array('search' => null, 'search_field' => 'summary', 'record_after' => null, 'date' => null, 'date_from' => null, 'date_to' => null, 'record' => null, 'record__in' => null, 'record__not_in' => null, 'records_per_page' => get_option('posts_per_page'), 'paged' => 1, 'order' => 'desc', 'orderby' => isset($args['search']) ? '_score' : 'date', 'meta' => array(), 'aggregations' => array(), 'fields' => null);
     // Additional property fields
     $properties = array('type' => 'stream', 'author' => null, 'author_role' => null, 'ip' => null, 'object_id' => null, 'site_id' => null, 'blog_id' => null, 'visibility' => 'publish', 'connector' => null, 'context' => null, 'action' => null);
     // Add property fields to defaults, including their __in/__not_in variations
     foreach ($properties as $property => $default) {
         if (!isset($defaults[$property])) {
             $defaults[$property] = $default;
         }
         $defaults["{$property}__in"] = array();
         $defaults["{$property}__not_in"] = array();
     }
     $args = wp_parse_args($args, $defaults);
     /**
      * Filter allows additional arguments to query $args
      *
      * @param  array  Array of query arguments
      * @return array  Updated array of query arguments
      */
     $args = apply_filters('wp_stream_query_args', $args);
     $query = array();
     $filters = array();
     $fields = array();
     // PARSE SEARCH
     if ($args['search']) {
         if ($args['search_field']) {
             $search_field = $args['search_field'];
             $query['query']['match'][$search_field] = $args['search'];
         } else {
             $query['query']['match']['summary'] = $args['search'];
         }
     }
     // PARSE FIELDS
     if ($args['fields']) {
         $fields = is_array($args['fields']) ? $args['fields'] : explode(',', $args['fields']);
     }
     // PARSE DATE
     if ($args['date_from']) {
         $filters[]['range']['created']['gte'] = wp_stream_get_iso_8601_extended_date(strtotime($args['date_from'] . ' 00:00:00'), get_option('gmt_offset'));
     }
     if ($args['date_to']) {
         $filters[]['range']['created']['lte'] = wp_stream_get_iso_8601_extended_date(strtotime($args['date_to'] . ' 23:59:59'), get_option('gmt_offset'));
     }
     if ($args['date']) {
         $filters[]['range']['created'] = array('gte' => wp_stream_get_iso_8601_extended_date(strtotime($args['date'] . ' 00:00:00'), get_option('gmt_offset')), 'lte' => wp_stream_get_iso_8601_extended_date(strtotime($args['date'] . ' 23:59:59'), get_option('gmt_offset')));
     }
     // PARSE RECORD
     if ($args['record_after']) {
         $filters[]['range']['created']['gt'] = date('c', strtotime($args['record_after']));
     }
     if ($args['record']) {
         $filters[]['ids']['values'] = array($args['record']);
     }
     if ($args['record__in']) {
         $filters[]['ids']['values'] = $args['record__in'];
     }
     if ($args['record__not_in']) {
         $filters[]['not']['ids']['values'] = $args['record__not_in'];
     }
     // PARSE PROPERTIES
     foreach ($properties as $property => $default) {
         if ($args[$property]) {
             $filters[]['term'][$property] = $args[$property];
         }
         if ($args["{$property}__in"]) {
             $property_in = array();
             foreach ($args["{$property}__in"] as $value) {
                 $property_in[]['term'][$property] = $value;
             }
             $filters[]['or'] = $property_in;
         }
         if ($args["{$property}__not_in"]) {
             foreach ($args["{$property}__not_in"] as $value) {
                 $filters[]['not']['term'][$property] = $value;
             }
         }
     }
     // PARSE PAGINATION
     if ($args['records_per_page']) {
         if ($args['records_per_page'] >= 0) {
             $query['size'] = (int) $args['records_per_page'];
         } else {
             $query['size'] = null;
         }
     } else {
         $query['size'] = get_option('posts_per_page', 20);
     }
     if ($args['paged']) {
         $query['from'] = ((int) $args['paged'] - 1) * $query['size'];
     }
     // PARSE ORDER
     $query['sort'] = array();
     $orderby = !empty($args['orderby']) ? $args['orderby'] : 'created';
     $order = !empty($args['order']) ? $args['order'] : 'desc';
     if ('date' === $orderby) {
         $orderby = 'created';
     }
     $query['sort'][][$orderby]['order'] = $order;
     // PARSE META
     if ($args['meta']) {
         $meta = (array) $args['meta'];
         foreach ($meta as $key => $values) {
             if (!is_array($values)) {
                 $values = (array) $values;
             }
             $filters[]['nested'] = array('path' => 'stream_meta', 'filter' => array('terms' => array($key => $values)));
         }
     }
     // PARSE AGGREGATIONS
     if (!empty($args['aggregations'])) {
         foreach ($args['aggregations'] as $aggregation_term) {
             $query['aggregations'][$aggregation_term]['terms']['field'] = $aggregation_term;
         }
     }
     // Add filters to query
     if (!empty($filters)) {
         if (count($filters) > 1) {
             $query['filter']['and'] = $filters;
         } else {
             $query['filter'] = current($filters);
         }
     }
     $query = apply_filters('wp_stream_db_query', $query);
     $fields = apply_filters('wp_stream_db_fields', $fields);
     /**
      * Query results
      * @var  array
      */
     return WP_Stream::$db->query($query, $fields);
 }
コード例 #7
0
    /**
     * Renders rows for Stream Activity Dashboard Widget
     *
     * @param  obj     Record to be inserted
     * @param  int     Row number
     *
     * @return string  Contents of new row
     */
    public static function widget_row($item)
    {
        $author = new WP_Stream_Author((int) $item->author, (array) $item->author_meta);
        $time_author = sprintf(_x('%1$s ago by <a href="%2$s">%3$s</a>', '1: Time, 2: User profile URL, 3: User display name', 'stream'), human_time_diff(strtotime($item->created)), esc_url($author->get_records_page_url()), esc_html($author->get_display_name()));
        if ($author->get_agent()) {
            $time_author .= sprintf(' %s', WP_Stream_Author::get_agent_label($author->get_agent()));
        }
        ob_start();
        ?>
		<li data-datetime="<?php 
        echo wp_stream_get_iso_8601_extended_date(strtotime($item->created));
        ?>
">
		<div class="record-avatar">
				<a href="<?php 
        echo esc_url($author->get_records_page_url());
        ?>
">
					<?php 
        echo $author->get_avatar_img(72);
        // xss ok
        ?>
				</a>
			</div>
		<span class="record-meta"><?php 
        echo $time_author;
        // xss ok
        ?>
</span>
		<br/>
		<?php 
        echo esc_html($item->summary);
        ?>
		</li>
		<?php 
        return ob_get_clean();
    }
コード例 #8
0
 function column_default($item, $column_name)
 {
     switch ($column_name) {
         case 'date':
             $created = date('Y-m-d H:i:s', strtotime($item->created));
             $date_string = sprintf('<time datetime="%s" class="relative-time record-created">%s</time>', wp_stream_get_iso_8601_extended_date(strtotime($item->created)), get_date_from_gmt($created, 'Y/m/d'));
             $out = $this->column_link($date_string, 'date', get_date_from_gmt($created, 'Y/m/d'));
             $out .= '<br />';
             $out .= get_date_from_gmt($created, 'h:i:s A');
             break;
         case 'summary':
             $out = $item->summary;
             if ($item->object_id) {
                 $out .= $this->column_link('<span class="dashicons dashicons-search stream-filter-object-id"></span>', array('object_id' => $item->object_id, 'context' => $item->context), null, __('View all records for this object', 'stream'));
             }
             $out .= $this->get_action_links($item);
             break;
         case 'author':
             $author = new WP_Stream_Author((int) $item->author, (array) $item->author_meta);
             $out = sprintf('<a href="%s">%s <span>%s</span></a>%s%s%s', $author->get_records_page_url(), $author->get_avatar_img(80), $author->get_display_name(), $author->is_deleted() ? sprintf('<br /><small class="deleted">%s</small>', esc_html__('Deleted User', 'stream')) : '', $author->get_role() ? sprintf('<br /><small>%s</small>', $author->get_role()) : '', $author->get_agent() ? sprintf('<br /><small>%s</small>', WP_Stream_Author::get_agent_label($author->get_agent())) : '');
             break;
         case 'context':
             $connector_title = $this->get_term_title($item->{'connector'}, 'connector');
             $context_title = $this->get_term_title($item->{'context'}, 'context');
             $out = $this->column_link($connector_title, 'connector', $item->{'connector'});
             $out .= '<br />&#8627;&nbsp;';
             $out .= $this->column_link($context_title, array('connector' => $item->{'connector'}, 'context' => $item->{'context'}));
             break;
         case 'action':
             $out = $this->column_link($this->get_term_title($item->{$column_name}, $column_name), $column_name, $item->{$column_name});
             break;
         case 'ip':
             $out = $this->column_link($item->{$column_name}, 'ip', $item->{$column_name});
             break;
         case 'blog_id':
             $blog = $item->blog_id && is_multisite() ? get_blog_details($item->blog_id) : WP_Stream_Network::get_instance()->get_network_blog();
             $out = sprintf('<a href="%s"><span>%s</span></a>', add_query_arg(array('blog_id' => $blog->blog_id), network_admin_url('admin.php?page=wp_stream')), esc_html($blog->blogname));
             break;
         default:
             /**
              * Registers new Columns to be inserted into the table.  The cell contents of this column is set
              * below with 'wp_stream_inster_column_default-'
              *
              * @param array $new_columns Array of new column titles to add
              */
             $inserted_columns = apply_filters('wp_stream_register_column_defaults', $new_columns = array());
             if (!empty($inserted_columns) && is_array($inserted_columns)) {
                 foreach ($inserted_columns as $column_title) {
                     /**
                      * If column title inserted via wp_stream_register_column_defaults ($column_title) exists
                      * among columns registered with get_columns ($column_name) and there is an action associated
                      * with this column, do the action
                      *
                      * Also, note that the action name must include the $column_title registered
                      * with wp_stream_register_column_defaults
                      */
                     if ($column_title == $column_name && has_action("wp_stream_insert_column_default-{$column_title}")) {
                         /**
                          * Allows for the addition of content under a specified column.
                          *
                          * @since 1.0.0
                          *
                          * @param object $item Contents of the row
                          */
                         $out = do_action("wp_stream_insert_column_default-{$column_title}", $item);
                     } else {
                         $out = $column_name;
                     }
                 }
             } else {
                 $out = $column_name;
                 // xss ok
             }
     }
     echo $out;
     // xss ok
 }