Skip to content

Commit 3d5eb29

Browse files
committed
Fixed replacement tags for comments module
1 parent 25a2d48 commit 3d5eb29

File tree

8 files changed

+385
-15
lines changed

8 files changed

+385
-15
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Fixed
66

77
- Enabled direct access to fields inside a FieldGroupContent model using a field name
8+
- Behavior of replacement tags for Comments module - `exp.comment.form` and `exp.comment.preview`
89

910
## [1.1.1] - 2023-06-15
1011

src/Bootstrap/ReplaceTemplateTags.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ public function bootstrap(Application $app)
2323
$exp->registerTag('channel.categories', \Expressionengine\Coilpack\View\Tags\Channel\Categories::class);
2424
$exp->registerTag('channel.entries', \Expressionengine\Coilpack\View\Tags\Channel\Entries::class);
2525
$exp->registerTag('comment.entries', \Expressionengine\Coilpack\View\Tags\Comment\Entries::class);
26+
$exp->registerTag('comment.form', \Expressionengine\Coilpack\View\Tags\Comment\Form::class);
27+
$exp->registerTag('comment.preview', \Expressionengine\Coilpack\View\Tags\Comment\Preview::class);
2628
$exp->registerTag('structure.entries', \Expressionengine\Coilpack\View\Tags\Structure\Entries::class);
2729
$exp->registerTag('structure.nav', \Expressionengine\Coilpack\View\Tags\Structure\Nav::class);
2830
$exp->registerTag('email.contact_form', \Expressionengine\Coilpack\View\Tags\Email\ContactForm::class);

src/Models/Addon/Action.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ class Action extends Model
1616
// Available as a replacement to ee()->functions->fetch_action_id
1717
public static function fetch_action_id($class, $method)
1818
{
19-
return static::select('action_id')->where('class', $class)->where('method', $method)->first()->action_id;
19+
$action = static::select('action_id')->where('class', $class)->where('method', $method)->first();
20+
21+
if (! $action) {
22+
throw new \Exception("Could not find action for '$class:$method', please make sure the module is installed.");
23+
}
24+
25+
return $action->action_id;
2026
}
2127
}

src/TemplateOutput.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,6 @@ public function __isset($key)
165165

166166
public function __call($method, $arguments)
167167
{
168-
return $this->object->{$method}(...$arguments);
168+
return $this->object ? $this->object->{$method}(...$arguments) : null;
169169
}
170170
}

src/View/FormTag.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
abstract class FormTag extends Tag
88
{
9+
protected $attributes = [];
10+
911
public function defineParameters(): array
1012
{
1113
return array_merge(parent::defineParameters(), [
@@ -87,7 +89,10 @@ public function open($data = [])
8789
$defaults['name'] = $this->getArgument('name')->value;
8890
}
8991

90-
$data = array_merge_recursive($defaults, $data);
92+
// Merge $data onto $defaults and do a deeper merge only on 'hidden_fields' array
93+
$hidden = array_merge($defaults['hidden_fields'], $data['hidden_fields'] ?? []);
94+
$data = array_merge($defaults, $data);
95+
$data['hidden_fields'] = $hidden;
9196

9297
$form = ee()->functions->form_declaration($data);
9398
$form = str_replace('{csrf_token}', $token, $form);
@@ -134,6 +139,16 @@ protected function decrypt($data)
134139
return ee('Encrypt')->decode($data, ee()->config->item('session_crypt_key'));
135140
}
136141

142+
public function __isset($key)
143+
{
144+
return array_key_exists($key, $this->attributes);
145+
}
146+
147+
public function __get($key)
148+
{
149+
return (array_key_exists($key, $this->attributes)) ? $this->attributes[$key] : null;
150+
}
151+
137152
/**
138153
* Cast the tag to a string by invoking the open method
139154
*

src/View/Tags/Comment/Form.php

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
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

Comments
 (0)