|
| 1 | +<?php |
| 2 | + |
| 3 | +namespace Expressionengine\Coilpack\View\Tags\Comment; |
| 4 | + |
| 5 | +use Expressionengine\Coilpack\Models\Addon\Action; |
| 6 | +use Expressionengine\Coilpack\Models\Channel\ChannelEntry; |
| 7 | +use Expressionengine\Coilpack\Support\Arguments\FilterArgument; |
| 8 | +use Expressionengine\Coilpack\Support\Parameter; |
| 9 | +use Expressionengine\Coilpack\Traits\InteractsWithAddon; |
| 10 | +use Expressionengine\Coilpack\View\FormTag; |
| 11 | + |
| 12 | +class Form extends FormTag |
| 13 | +{ |
| 14 | + use InteractsWithAddon; |
| 15 | + |
| 16 | + public function defineParameters(): array |
| 17 | + { |
| 18 | + return array_merge(parent::defineParameters(), [ |
| 19 | + new Parameter([ |
| 20 | + 'name' => 'entry_id', |
| 21 | + 'type' => 'string', |
| 22 | + 'description' => 'Display a comment form for a specific channel entry', |
| 23 | + ]), |
| 24 | + new Parameter([ |
| 25 | + 'name' => 'preview', |
| 26 | + 'type' => 'string', |
| 27 | + 'description' => 'Which template path should be used for comment previews', |
| 28 | + ]), |
| 29 | + new Parameter([ |
| 30 | + 'name' => 'url_title', |
| 31 | + 'type' => 'string', |
| 32 | + 'description' => 'Display a comment form for a specific channel entry by its URL title', |
| 33 | + ]), |
| 34 | + new Parameter([ |
| 35 | + 'name' => 'channel', |
| 36 | + 'type' => 'string', |
| 37 | + 'description' => 'Specify which channel to associate with the submitted comment', |
| 38 | + ]), |
| 39 | + ]); |
| 40 | + } |
| 41 | + |
| 42 | + public function getChannelArgument($value) |
| 43 | + { |
| 44 | + return new FilterArgument($value); |
| 45 | + } |
| 46 | + |
| 47 | + public function getEntryStatusArgument($value) |
| 48 | + { |
| 49 | + $value = str_replace(['Open', 'Closed'], ['open', 'closed'], $value); |
| 50 | + |
| 51 | + return new FilterArgument($value); |
| 52 | + } |
| 53 | + |
| 54 | + public function __construct() |
| 55 | + { |
| 56 | + // Load the form helper and session library |
| 57 | + ee()->load->helper('form'); |
| 58 | + ee()->load->library('session'); |
| 59 | + |
| 60 | + $this->addonInstance = $this->getAddonInstance('email'); |
| 61 | + |
| 62 | + // Conditionals |
| 63 | + $data = [ |
| 64 | + 'logged_in' => (ee()->session->userdata('member_id') != 0), |
| 65 | + 'logged_out' => (ee()->session->userdata('member_id') == 0), |
| 66 | + 'captcha' => ee('Captcha')->shouldRequireCaptcha() ? ee('Captcha')->create() : null, |
| 67 | + ]; |
| 68 | + |
| 69 | + // Process default variables |
| 70 | + $postVars = ['screen_name' => 'name', 'email', 'url', 'location', 'comment', 'save_info', 'notify_me']; |
| 71 | + foreach ($postVars as $userKey => $key) { |
| 72 | + $userKey = is_numeric($userKey) ? $key : $userKey; |
| 73 | + // Adding slashes since they removed in _setup_form |
| 74 | + $var = addslashes( |
| 75 | + \form_prep( |
| 76 | + ee()->functions->encode_ee_tags( |
| 77 | + ee()->input->post($key, true) ?: (ee()->session->userdata[$userKey] ?? null), |
| 78 | + true |
| 79 | + ), |
| 80 | + $key |
| 81 | + ) |
| 82 | + ); |
| 83 | + |
| 84 | + $data[$key] = $var; |
| 85 | + } |
| 86 | + |
| 87 | + if (! isset($_POST['PRV'])) { |
| 88 | + $data['save_info'] = (! isset(ee()->session->userdata['notify_by_default'])) ? ee()->input->cookie('save_info') : ee()->session->userdata['notify_by_default']; |
| 89 | + } |
| 90 | + |
| 91 | + if (empty($data['notify_me']) && ! isset($_POST['PRV'])) { |
| 92 | + $data['notify_me'] = (ee()->input->cookie('notify_me')) ?: ee()->session->userdata('notify_by_default', 'n') == 'y'; |
| 93 | + } |
| 94 | + |
| 95 | + // Default URL value |
| 96 | + $data['url'] = $data['url'] ?: 'http://'; |
| 97 | + $data['notify_me'] = $data['notify_me'] === true || $data['notify_me'] == 'yes'; |
| 98 | + $data['save_info'] = $data['save_info'] === true || $data['save_info'] == 'yes'; |
| 99 | + |
| 100 | + $memberVars = [ |
| 101 | + 'member_name' => (ee()->session->userdata['screen_name'] != '') ? ee()->session->userdata['screen_name'] : ee()->session->userdata['username'], |
| 102 | + 'member_email' => (ee()->session->userdata['email'] == '') ? '' : ee()->session->userdata['email'], |
| 103 | + ]; |
| 104 | + |
| 105 | + foreach ($memberVars as $key => $value) { |
| 106 | + $data[$key] = \form_prep(ee()->functions->encode_ee_tags($value, true)); |
| 107 | + } |
| 108 | + |
| 109 | + $data['current_time'] = \Carbon\Carbon::now(); |
| 110 | + |
| 111 | + $this->attributes = $data; |
| 112 | + } |
| 113 | + |
| 114 | + public function open($data = []) |
| 115 | + { |
| 116 | + $data = [ |
| 117 | + 'ACT' => Action::fetch_action_id('Comment', 'insert_new_comment'), |
| 118 | + 'RET' => $this->encrypt($this->hasArgument('return') ? $this->getArgument('return')->value : ee()->uri->uri_string), |
| 119 | + 'PRV' => (isset($_POST['PRV'])) ? $_POST['PRV'] : $this->getArgument('preview')->value, |
| 120 | + 'entry_id' => $this->entry->entry_id ?? '', |
| 121 | + ]; |
| 122 | + |
| 123 | + return parent::open(['hidden_fields' => $data]); |
| 124 | + } |
| 125 | + |
| 126 | + public function close() |
| 127 | + { |
| 128 | + $res = parent::close(); |
| 129 | + /** |
| 130 | + * 'comment_form_end' hook. |
| 131 | + * Modify, add, etc. something to the comment form at end of processing |
| 132 | + */ |
| 133 | + if (ee()->extensions->active_hook('comment_form_end') === true) { |
| 134 | + $res = ee()->extensions->call('comment_form_end', $res); |
| 135 | + if (ee()->extensions->end_script === true) { |
| 136 | + return $res; |
| 137 | + } |
| 138 | + } |
| 139 | + |
| 140 | + return $res; |
| 141 | + } |
| 142 | + |
| 143 | + public function run() |
| 144 | + { |
| 145 | + $entry = $this->findEntry(); |
| 146 | + |
| 147 | + /** ---------------------------------------- |
| 148 | + /** Smart Notifications? Mark comments as read. |
| 149 | + /** ----------------------------------------*/ |
| 150 | + if ($entry && ee()->session->userdata('smart_notifications') == 'y') { |
| 151 | + ee()->load->library('subscription'); |
| 152 | + ee()->subscription->init('comment', ['entry_id' => $entry->entry_id], true); |
| 153 | + ee()->subscription->mark_as_read(); |
| 154 | + } |
| 155 | + |
| 156 | + $attributes = [ |
| 157 | + 'entry' => $entry, |
| 158 | + 'comments_disabled' => $entry ? $this->commentsDisabledForEntry($entry) : null, |
| 159 | + 'comments_expired' => $entry ? $this->commentsExpiredForEntry($entry) : null, |
| 160 | + ]; |
| 161 | + |
| 162 | + $this->attributes = array_merge($this->attributes, $attributes); |
| 163 | + |
| 164 | + return parent::run(); |
| 165 | + } |
| 166 | + |
| 167 | + protected function findEntry() |
| 168 | + { |
| 169 | + // Figure out the right entry ID |
| 170 | + // Order of precedence: POST, entry_id=, url_title=, $qstring |
| 171 | + $where = array_filter([ |
| 172 | + 'entry_id' => $_POST['entry_id'] ?? $this->getArgument('entry_id')->value, |
| 173 | + 'url_title' => $this->getArgument('url_title')->value, |
| 174 | + ]); |
| 175 | + |
| 176 | + if (empty($where)) { |
| 177 | + $qstring = ee()->uri->query_string; |
| 178 | + |
| 179 | + /** -------------------------------------- |
| 180 | + /** Remove page number |
| 181 | + /** --------------------------------------*/ |
| 182 | + if (preg_match("#(^|/)P(\d+)(/|$)#", $qstring, $match)) { |
| 183 | + $qstring = trim(reduce_double_slashes(str_replace($match['0'], '/', $qstring)), '/'); |
| 184 | + } |
| 185 | + |
| 186 | + // If there is a slash in the entry ID we'll kill everything after it. |
| 187 | + $entry_id = trim($qstring); |
| 188 | + $entry_id = preg_replace('#/.+#', '', $entry_id); |
| 189 | + |
| 190 | + $where = ! is_numeric($entry_id) ? ['url_title' => $entry_id] : ['entry_id' => $entry_id]; |
| 191 | + } |
| 192 | + |
| 193 | + $query = ChannelEntry::where(array_key_first($where), current($where)) |
| 194 | + ->whereIn('site_id', ee()->TMPL->site_ids); |
| 195 | + |
| 196 | + $query->when($this->hasArgument('channel'), function ($query) { |
| 197 | + $query->whereHas('channel', function ($query) { |
| 198 | + $this->getArgument('channel')->addQuery($query, 'channel_name'); |
| 199 | + $query->whereIn('site_id', ee()->TMPL->site_ids); |
| 200 | + }); |
| 201 | + }); |
| 202 | + |
| 203 | + $query->when($this->hasArgument('entry_status'), function ($query) { |
| 204 | + $this->getArgument('entry_status')->addQuery($query, 'entry_status'); |
| 205 | + |
| 206 | + if (stristr($this->getArgument('entry_status')->value, 'closed') === false) { |
| 207 | + $query->where('status', '!=', 'closed'); |
| 208 | + } |
| 209 | + }, function ($query) { |
| 210 | + $query->where('status', '!=', 'closed'); |
| 211 | + }); |
| 212 | + |
| 213 | + return $query->first(); |
| 214 | + } |
| 215 | + |
| 216 | + /** |
| 217 | + * Check whether comments are disabled for the given entry |
| 218 | + * |
| 219 | + * @return bool |
| 220 | + */ |
| 221 | + protected function commentsDisabledForEntry(ChannelEntry $entry) |
| 222 | + { |
| 223 | + return $entry->allow_comments == false |
| 224 | + || $entry->channel->comment_system_enabled == false |
| 225 | + || ee()->config->item('enable_comments') != 'y' |
| 226 | + || ! ee('Permission')->can('post_comments'); |
| 227 | + } |
| 228 | + |
| 229 | + /** |
| 230 | + * Check whether comments are expired for the given entry |
| 231 | + * |
| 232 | + * @return bool |
| 233 | + */ |
| 234 | + protected function commentsExpiredForEntry(ChannelEntry $entry) |
| 235 | + { |
| 236 | + if (ee()->config->item('comment_moderation_override') === 'y' || $entry->comment_expiration_date <= 0) { |
| 237 | + return false; |
| 238 | + } |
| 239 | + |
| 240 | + return ee()->localize->now > $entry->comment_expiration_date; |
| 241 | + } |
| 242 | +} |
0 commit comments