Completed
Push — master ( 2c9aff...c22bdd )
by Jacob
03:13
created

CommentSubmitModule::save_comment()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 18
rs 9.4285
cc 2
eloc 12
nc 2
nop 0
1
<?
0 ignored issues
show
Security Best Practice introduced by
It is not recommend to use PHP's short opening tag <?, better use <?php, or <?= in case of outputting.

Short opening tags are disabled in PHP’s default configuration. In such a case, all content of this file is output verbatim to the browser without being parsed, or executed.

As a precaution to avoid these problems better use the long opening tag <?php.

Loading history...
2
3
Loader::load('collector', 'comment/CommentCollector');
4
5
Loader::load('utility', array(
6
	'Content',
7
	'Cookie',
8
	'Request',
9
	'Validate'));
10
11
final class CommentSubmitModule
12
{
13
14
	private $site;
15
	private $path;
16
	private $full_path;
17
	private $page_title;
18
19
	public function __construct($site, $path, $full_path, $page_title)
20
	{
21
		$this->site = $site;
22
		$this->path = $path;
23
		$this->full_path = $full_path;
24
		$this->page_title = $page_title;
25
	}
26
27
	public function activate()
28
	{
29
		if(!Request::hasPost())
30
			return false;
31
		if(!Request::getPost('submit') == 'Submit Comment')
32
			return false;
33
		
34
		$errors = $this->fetch_errors();
35
		if(count($errors) > 0)
36
			return $errors;
37
		if(Request::getPost('catch') !== '')
38
			return false;
39
		
40
		$page_id = $this->save_comment_page();
41
		$commenter_id = $this->save_commenter();
42
		$comment_id = $this->save_comment();
43
		
44
		$comment_meta_id = $this->save_comment_meta($commenter_id, $comment_id, $page_id);
45
		
46
		$this->send_notifications($page_id);
47
		$this->redirect_to_comment($comment_meta_id);
48
	}
49
50
	private function fetch_errors()
51
	{
52
		$errors = array();
53
		if(!Validate::checkRequest('post', 'name', 'name'))
54
			$errors['name'] = 'You must include a valid name';
55
		if(!Validate::checkRequest('post', 'email', 'email'))
56
			$errors['email'] = 'You must include a valid email';
57
		if(Request::getPost('website') && !Validate::checkRequest('post', 'website', 'url'))
58
			$errors['website'] = 'Please enter a valid website';
59
		if(!Validate::checkRequest('post', 'comment', 'string'))
60
			$errors['comment'] = 'You must enter a comment';
61
		if(Request::getPost('notify') && Request::getPost('notify') != 'check')
62
			$errors['notify'] = 'You entered an invalid notify request';
63
		if(Request::getPost('reply') && !Validate::checkRequest('post', 'reply', 'integer'))
64
			$errors['reply'] = 'You entered an invalid reply request';
65
		
66
		return $errors;
67
	}
68
69
	private function save_comment_page()
70
	{
71
		$page_result = CommentCollector::getCommentPageByURL($this->path, $this->site);
72
		if($page_result !== null)
73
			return $page_result->id;
74
		
75
		$query = "INSERT INTO `jpemeric_comment`.`comment_page` (`site`, `path`) VALUES ('%d', '%s')";
76
		$query = sprintf($query, $this->site, $this->path);
77
		Database::execute($query);
78
		
79
		return Database::lastInsertID();
80
	}
81
82
	private function save_commenter()
83
	{
84
		$cookie_value = array(
85
			'name' => Request::getPost('name'),
86
			'email' => Request::getPost('email'));
87
		
88
		if(Request::getPost('website') != '')
89
			$cookie_value['website'] = Request::getPost('website');
90
		
91
		$cookie_value = json_encode($cookie_value);
92
		
93
		Cookie::instance('Commenter')
94
			->setValue($cookie_value)
95
			->save();
96
		
97
		$commenter_result = CommentCollector::getCommenterByFields(Request::getPost('name'), Request::getPost('email'), Request::getPost('website'));
98
		if($commenter_result !== null)
99
			return $commenter_result->id;
100
		
101
		$query = "INSERT INTO `jpemeric_comment`.`commenter` (`name`,`email`,`url`) VALUES ('%s','%s','%s')";
102
		
103
		$name = Database::escape(Request::getPost('name'));
104
		$email = Database::escape(Request::getPost('email'));
105
		$website = Database::escape(Request::getPost('website'));
106
		
107
		$query = sprintf($query, $name, $email, $website);
108
		Database::execute($query);
109
		return Database::lastInsertID();
110
	}
111
112
	private function save_comment()
113
	{
114
		$comment_result = CommentCollector::getCommentByBody(Request::getPost('comment'));
115
		if($comment_result !== null)
116
			return $comment_result->id;
117
		
118
		$query = "INSERT INTO `jpemeric_comment`.`comment` (`body`, `body_format`) VALUES ('%s', '%s')";
119
		
120
		$body = Database::escape(Request::getPost('comment'));
121
		
122
		$body_format = Request::getPost('comment');
123
		$body_format = Content::instance('CleanComment', $body_format)->activate();
124
		$body_format = Database::escape($body_format);
125
		
126
		$query = sprintf($query, $body, $body_format);
127
		Database::execute($query);
128
		return Database::lastInsertID();
129
	}
130
131
	private function save_comment_meta($commenter, $comment, $page)
132
	{
133
		$query = "INSERT INTO `jpemeric_comment`.`comment_meta` (`commenter`,`comment`,`reply`,`notify`,`comment_page`,`date`,`display`) VALUES ('%d','%d','%d','%d','%d','%s','%d')";
134
		
135
		$reply = Database::escape(Request::getPost('type'));
136
		if($reply == 'new')
137
			$reply = 0;
138
		// else check to make sure value is legit
139
		
140
		$notify = (Request::getPost('notify') == 'check') ? 1 : 0;
141
		$date = date('Y-m-d H:i:s');
142
		$display = 1;
143
		
144
		$query = sprintf($query, $commenter, $comment, $reply, $notify, $page, $date, $display);
145
		Database::execute($query);
146
		return Database::lastInsertID();
147
	}
148
149
	private function send_notifications($page)
150
	{
151
		Loader::load('utility', 'Mail');
152
		
153
		$email_recipient_array = array();
154
		
155
		$commenter_result = CommentCollector::getCommenterByFields(Request::getPost('name'), Request::getPost('email'), Request::getPost('website'));
156
		
157
		if($commenter_result->trusted == 1)
158
		{
159
			$notification_result = CommentCollector::getNotificationForPage($page);
160
			
161
			foreach($notification_result as $notification_row)
0 ignored issues
show
Bug introduced by
The expression $notification_result of type array|false is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
162
			{
163
				if($notification_row->email == Request::getPost('email'))
164
					continue;
165
				
166
				$email_recipient_array[$notification_row->email] = array(
167
					'email' => $notification_row->email,
168
					'name' => $notification_row->name);
169
			}
170
		}
171
        
172
        $site = URLDecode::getSite();
173
        
174
        if ($site == 'blog') {
175
            $subject = "New Comment on Jacob Emerick's Blog";
176
            $message = "Hello!\nThere has been a new comment on the post '{$this->page_title}' at Jacob Emerick's Blog. You have chosen to be notified of it - please reply to [email protected] if you would like to be removed from these notifications.\n\nOn " . date('F j, Y g:i a') . ", " . Request::getPost('name') . " commented...\n" . Request::getPost('comment') . "\n\nVisit {$this->full_path}#comments to see and reply to all the comments on this post.\nThank you!";
177
        } else if ($site == 'waterfalls') {
178
            $subject = "New Comment on Waterfalls of the Keweenaw";
179
            $message = "Hello!\nThere has been a new comment on the page '{$this->page_title}' at Waterfalls of the Keweenaw. You have chosen to be notified of it - please reply to [email protected] if you would like to be removed from these notifications.\n\nOn " . date('F j, Y g:i a') . ", " . Request::getPost('name') . " commented...\n" . Request::getPost('comment') . "\n\nVisit {$this->full_path}#comments to see and reply to all the comments on this post.\nThank you!";
180
        }
181
182
    global $container;
183
184
		foreach($email_recipient_array as $email_recipient)
185
		{
186
      $sent = $container['mail']
0 ignored issues
show
Unused Code introduced by
$sent is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
187
        ->addTo($email_recipient['email'], $email_recipient['name'])
188
        ->addBCC($container['config']->admin_email)
189
        ->setSubject($subject)
0 ignored issues
show
Bug introduced by
The variable $subject does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
190
        ->setMessage($message)
0 ignored issues
show
Bug introduced by
The variable $message does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
191
        ->send();		
192
		}
193
	}
194
195
	private function redirect_to_comment($comment_id)
196
	{
197
		$url = '';
198
		$url .= $this->full_path;
199
		$url .= "#comment-{$comment_id}";
200
		
201
		Loader::loadNew('controller', 'Error303Controller', array($url))->activate();
202
		exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method redirect_to_comment() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
203
	}
204
205
}
206