GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — develop (#1827)
by
unknown
18:14
created

documentController   F

Complexity

Total Complexity 426

Size/Duplication

Total Lines 2539
Duplicated Lines 12.6 %

Coupling/Cohesion

Components 1
Dependencies 11
Metric Value
wmc 426
lcom 1
cbo 11
dl 320
loc 2539
rs 3.9999

53 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 3 1
A deleteDocumentHistory() 0 9 4
A addGrant() 0 4 1
F insertDocument() 47 159 50
F updateDocument() 72 229 56
A _deleteDocumentReadedLog() 0 4 1
A _deleteDocumentVotedLog() 0 4 1
A updateCommentCount() 0 22 3
B procDocumentVoteUp() 21 21 5
A insertAlias() 0 11 1
B procDocumentVoteDown() 21 21 5
A procDocumentDeclare() 9 9 3
A deleteDocumentAliasByModule() 0 6 1
A deleteDocumentAliasByDocument() 0 6 1
B triggerDeleteModuleDocuments() 0 23 4
D deleteDocument() 10 82 14
A _deleteDeclaredDocuments() 0 5 1
C moveDocumentToTrash() 21 110 12
C updateReadedCount() 0 63 10
D insertDocumentExtraKey() 0 37 10
C deleteDocumentExtraKeys() 0 56 10
B insertDocumentExtraVar() 0 15 6
B deleteDocumentExtraVars() 0 11 5
F updateVotedCount() 10 117 18
D declaredDocument() 16 104 15
A updateTrackbackCount() 0 16 2
B insertCategory() 0 26 4
A updateCategoryListOrder() 0 7 1
A updateCategoryCount() 0 14 3
A updateCategory() 0 6 2
C deleteCategory() 0 47 8
A deleteModuleCategory() 0 7 1
B moveCategoryUp() 0 41 6
B moveCategoryDown() 0 39 5
B addXmlJsFilter() 0 32 5
D procDocumentInsertCategory() 0 69 13
C procDocumentMoveCategory() 0 59 11
B procDocumentDeleteCategory() 0 36 5
A procDocumentMakeXmlFile() 0 15 2
D makeCategoryFile() 7 106 9
C getXmlTree() 2 64 11
C getPhpCacheCode() 26 90 10
A addDocumentPopupMenu() 14 14 2
C procDocumentAddCart() 0 68 18
F procDocumentManageCheckedDocument() 11 121 29
C procDocumentInsertModuleConfig() 8 31 8
B procDocumentTempSave() 7 61 8
B procDocumentGetList() 0 22 4
B _checkCommentStatusForOldVersion() 0 8 5
B _checkDocumentStatusForOldVersion() 0 5 5
A updateUploaedCount() 0 18 3
B triggerCopyModuleExtraKeys() 4 17 5
A triggerCopyModule() 14 14 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like documentController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use documentController, and based on these observations, apply Extract Interface, too.

1
<?php
2
/* Copyright (C) NAVER <http://www.navercorp.com> */
3
/**
4
 * documentController class
5
 * document the module's controller class
6
 *
7
 * @author NAVER ([email protected])
8
 * @package /modules/document
9
 * @version 0.1
10
 */
11
class documentController extends document
12
{
13
	/**
14
	 * Initialization
15
	 * @return void
16
	 */
17
	function init()
18
	{
19
	}
20
21
	/**
22
	 * Action to handle vote-up of the post (Up)
23
	 * @return Object
24
	 */
25 View Code Duplication
	function procDocumentVoteUp()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
26
	{
27
		if(!Context::get('is_logged')) return new Object(-1, 'msg_invalid_request');
28
29
		$document_srl = Context::get('target_srl');
30
		if(!$document_srl) return new Object(-1, 'msg_invalid_request');
31
32
		$oDocumentModel = getModel('document');
33
		$oDocument = $oDocumentModel->getDocument($document_srl, false, false);
34
		$module_srl = $oDocument->get('module_srl');
35
		if(!$module_srl) return new Object(-1, 'msg_invalid_request');
36
37
		$oModuleModel = getModel('module');
38
		$document_config = $oModuleModel->getModulePartConfig('document',$module_srl);
39
		if($document_config->use_vote_up=='N') return new Object(-1, 'msg_invalid_request');
40
41
		$point = 1;
42
		$output = $this->updateVotedCount($document_srl, $point);
43
		$this->add('voted_count', $output->get('voted_count'));
44
		return $output;
45
	}
46
47
	/**
48
	 * insert alias
49
	 * @param int $module_srl
50
	 * @param int $document_srl
51
	 * @param string $alias_title
52
	 * @return object
53
	 */
54
	function insertAlias($module_srl, $document_srl, $alias_title)
55
	{
56
		$args = new stdClass;
57
		$args->alias_srl = getNextSequence();
58
		$args->module_srl = $module_srl;
59
		$args->document_srl = $document_srl;
60
		$args->alias_title = urldecode($alias_title);
61
		$query = "document.insertAlias";
62
		$output = executeQuery($query, $args);
63
		return $output;
64
	}
65
66
	/**
67
	 * Action to handle vote-up of the post (Down)
68
	 * @return Object
69
	 */
70 View Code Duplication
	function procDocumentVoteDown()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
71
	{
72
		if(!Context::get('is_logged')) return new Object(-1, 'msg_invalid_request');
73
74
		$document_srl = Context::get('target_srl');
75
		if(!$document_srl) return new Object(-1, 'msg_invalid_request');
76
77
		$oDocumentModel = getModel('document');
78
		$oDocument = $oDocumentModel->getDocument($document_srl, false, false);
79
		$module_srl = $oDocument->get('module_srl');
80
		if(!$module_srl) return new Object(-1, 'msg_invalid_request');
81
82
		$oModuleModel = getModel('module');
83
		$document_config = $oModuleModel->getModulePartConfig('document',$module_srl);
84
		if($document_config->use_vote_down=='N') return new Object(-1, 'msg_invalid_request');
85
86
		$point = -1;
87
		$output = $this->updateVotedCount($document_srl, $point);
88
		$this->add('blamed_count', $output->get('blamed_count'));
89
		return $output;
90
	}
91
92
	/**
93
	 * Action called when the post is reported by other member
94
	 * @return void|Object
95
	 */
96 View Code Duplication
	function procDocumentDeclare()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
97
	{
98
		if(!Context::get('is_logged')) return new Object(-1, 'msg_invalid_request');
99
100
		$document_srl = Context::get('target_srl');
101
		if(!$document_srl) return new Object(-1, 'msg_invalid_request');
102
103
		return $this->declaredDocument($document_srl);
104
	}
105
106
	/**
107
	 * Delete alias when module deleted
108
	 * @param int $module_srl
109
	 * @return void
110
	 */
111
	function deleteDocumentAliasByModule($module_srl)
112
	{
113
		$args = new stdClass();
114
		$args->module_srl = $module_srl;
115
		executeQuery("document.deleteAlias", $args);
116
	}
117
118
	/**
119
	 * Delete alias when document deleted
120
	 * @param int $document_srl
121
	 * @return void
122
	 */
123
	function deleteDocumentAliasByDocument($document_srl)
124
	{
125
		$args = new stdClass();
126
		$args->document_srl = $document_srl;
127
		executeQuery("document.deleteAlias", $args);
128
	}
129
130
	/**
131
	 * Delete document history
132
	 * @param int $history_srl
133
	 * @param int $document_srl
134
	 * @param int $module_srl
135
	 * @return void
136
	 */
137
	function deleteDocumentHistory($history_srl, $document_srl, $module_srl)
138
	{
139
		$args = new stdClass();
140
		$args->history_srl = $history_srl;
141
		$args->module_srl = $module_srl;
142
		$args->document_srl = $document_srl;
143
		if(!$args->history_srl && !$args->module_srl && !$args->document_srl) return;
144
		executeQuery("document.deleteHistory", $args);
145
	}
146
147
	/**
148
	 * A trigger to delete all posts together when the module is deleted
149
	 * @param object $obj
150
	 * @return Object
151
	 */
152
	function triggerDeleteModuleDocuments(&$obj)
153
	{
154
		$module_srl = $obj->module_srl;
155
		if(!$module_srl) return new Object();
156
		// Delete the document
157
		$oDocumentAdminController = getAdminController('document');
158
		$output = $oDocumentAdminController->deleteModuleDocument($module_srl);
159
		if(!$output->toBool()) return $output;
160
		// Delete the category
161
		$oDocumentController = getController('document');
162
		$output = $oDocumentController->deleteModuleCategory($module_srl);
163
		if(!$output->toBool()) return $output;
164
		// Delete extra key and variable, because module deleted
165
		$this->deleteDocumentExtraKeys($module_srl);
166
167
		// remove aliases
168
		$this->deleteDocumentAliasByModule($module_srl);
169
170
		// remove histories
171
		$this->deleteDocumentHistory(null, null, $module_srl);
172
173
		return new Object();
174
	}
175
176
	/**
177
	 * Grant a permisstion of the document
178
	 * Available in the current connection with session value
179
	 * @param int $document_srl
180
	 * @return void
181
	 */
182
	function addGrant($document_srl)
183
	{
184
		$_SESSION['own_document'][$document_srl] = true;
185
	}
186
187
	/**
188
	 * Insert the document
189
	 * @param object $obj
190
	 * @param bool $manual_inserted
191
	 * @param bool $isRestore
192
	 * @return object
193
	 */
194
	function insertDocument($obj, $manual_inserted = false, $isRestore = false, $isLatest = true)
195
	{
196
		if(!$manual_inserted && !checkCSRF())
197
		{
198
			return new Object(-1, 'msg_invalid_request');
199
		}
200
201
		// begin transaction
202
		$oDB = &DB::getInstance();
203
		$oDB->begin();
204
		// List variables
205
		if($obj->comment_status) $obj->commentStatus = $obj->comment_status;
206
		if(!$obj->commentStatus) $obj->commentStatus = 'DENY';
207
		if($obj->commentStatus == 'DENY') $this->_checkCommentStatusForOldVersion($obj);
208
		if($obj->allow_trackback!='Y') $obj->allow_trackback = 'N';
209 View Code Duplication
		if($obj->homepage) 
210
		{
211
			$obj->homepage = removeHackTag($obj->homepage);
212
			if(!preg_match('/^[a-z]+:\/\//i',$obj->homepage))
213
			{
214
				$obj->homepage = 'http://'.$obj->homepage;
215
			}
216
		}
217
		
218
		if($obj->notify_message != 'Y') $obj->notify_message = 'N';
219
		if(!$obj->email_address) $obj->email_address = '';
220
		if(!$isRestore) $obj->ipaddress = $_SERVER['REMOTE_ADDR'];
221
222
                // can modify regdate only manager
223
                $grant = Context::get('grant');
224
		if(!$grant->manager)
225
		{
226
			unset($obj->regdate);
227
		}
228
		
229
		// Serialize the $extra_vars, check the extra_vars type, because duplicate serialized avoid
230
		if(!is_string($obj->extra_vars)) $obj->extra_vars = serialize($obj->extra_vars);
231
		// Remove the columns for automatic saving
232
		unset($obj->_saved_doc_srl);
233
		unset($obj->_saved_doc_title);
234
		unset($obj->_saved_doc_content);
235
		unset($obj->_saved_doc_message);
236
		// Call a trigger (before)
237
		$output = ModuleHandler::triggerCall('document.insertDocument', 'before', $obj);
238
		if(!$output->toBool()) return $output;
239
		// Register it if no given document_srl exists
240 View Code Duplication
		if(!$obj->document_srl) $obj->document_srl = getNextSequence();
241
		elseif(!$manual_inserted && !$isRestore && !checkUserSequence($obj->document_srl)) return new Object(-1, 'msg_not_permitted');
242
243
		$oDocumentModel = getModel('document');
244
		// Set to 0 if the category_srl doesn't exist
245
		if($obj->category_srl)
246
		{
247
			$category_list = $oDocumentModel->getCategoryList($obj->module_srl);
248
			if(count($category_list) > 0 && !$category_list[$obj->category_srl]->grant)
249
			{
250
				return new Object(-1, 'msg_not_permitted');
251
			}
252
			if(count($category_list) > 0 && !$category_list[$obj->category_srl]) $obj->category_srl = 0;
253
		}
254
		// Set the read counts and update order.
255
		if(!$obj->readed_count) $obj->readed_count = 0;
256
		if($isLatest) $obj->update_order = $obj->list_order = $obj->document_srl * -1;
257
		else $obj->update_order = $obj->list_order;
258
		// Check the status of password hash for manually inserting. Apply hashing for otherwise.
259
		if($obj->password && !$obj->password_is_hashed)
260
		{
261
			$obj->password = getModel('member')->hashPassword($obj->password);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class ModuleObject as the method hashPassword() does only exist in the following sub-classes of ModuleObject: memberModel. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
262
		}
263
		// Insert member's information only if the member is logged-in and not manually registered.
264
		$logged_info = Context::get('logged_info');
265
		if(Context::get('is_logged') && !$manual_inserted && !$isRestore)
266
		{
267
			$obj->member_srl = $logged_info->member_srl;
268
269
			// user_id, user_name and nick_name already encoded
270
			$obj->user_id = htmlspecialchars_decode($logged_info->user_id);
271
			$obj->user_name = htmlspecialchars_decode($logged_info->user_name);
272
			$obj->nick_name = htmlspecialchars_decode($logged_info->nick_name);
273
			$obj->email_address = $logged_info->email_address;
274
			$obj->homepage = $logged_info->homepage;
275
		}
276
		// If the tile is empty, extract string from the contents.
277
		$obj->title = htmlspecialchars($obj->title);
278
		settype($obj->title, "string");
279 View Code Duplication
		if($obj->title == '') $obj->title = cut_str(trim(strip_tags(nl2br($obj->content))),20,'...');
280
		// If no tile extracted from the contents, leave it untitled.
281
		if($obj->title == '') $obj->title = 'Untitled';
282
		// Remove XE's own tags from the contents.
283
		$obj->content = preg_replace('!<\!--(Before|After)(Document|Comment)\(([0-9]+),([0-9]+)\)-->!is', '', $obj->content);
284 View Code Duplication
		if(Mobile::isFromMobilePhone())
285
		{
286
			if($obj->use_html != 'Y')
287
			{
288
				$obj->content = htmlspecialchars($obj->content, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
289
			}
290
			$obj->content = nl2br($obj->content);
291
		}
292
		// Remove iframe and script if not a top adminisrator in the session.
293
		if($logged_info->is_admin != 'Y') $obj->content = removeHackTag($obj->content);
294
		// An error appears if both log-in info and user name don't exist.
295
		if(!$logged_info->member_srl && !$obj->nick_name) return new Object(-1,'msg_invalid_request');
296
297
		$obj->lang_code = Context::getLangType();
298
		// Insert data into the DB
299
		if(!$obj->status) $this->_checkDocumentStatusForOldVersion($obj);
300
		$output = executeQuery('document.insertDocument', $obj);
301
		if(!$output->toBool())
302
		{
303
			$oDB->rollback();
304
			return $output;
305
		}
306
		// Insert extra variables if the document successfully inserted.
307
		$extra_keys = $oDocumentModel->getExtraKeys($obj->module_srl);
308 View Code Duplication
		if(count($extra_keys))
309
		{
310
			foreach($extra_keys as $idx => $extra_item)
311
			{
312
				$value = NULL;
313
				if(isset($obj->{'extra_vars'.$idx}))
314
				{
315
					$tmp = $obj->{'extra_vars'.$idx};
316
					if(is_array($tmp))
317
						$value = implode('|@|', $tmp);
318
					else
319
						$value = trim($tmp);
320
				}
321
				else if(isset($obj->{$extra_item->name})) $value = trim($obj->{$extra_item->name});
322
				if($value == NULL) continue;
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $value of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
323
324
				$this->insertDocumentExtraVar($obj->module_srl, $obj->document_srl, $idx, $value, $extra_item->eid);
325
			}
326
		}
327
		// Update the category if the category_srl exists.
328
		if($obj->category_srl) $this->updateCategoryCount($obj->module_srl, $obj->category_srl);
329
		// Call a trigger (after)
330 View Code Duplication
		if($output->toBool())
331
		{
332
			$trigger_output = ModuleHandler::triggerCall('document.insertDocument', 'after', $obj);
333
			if(!$trigger_output->toBool())
334
			{
335
				$oDB->rollback();
336
				return $trigger_output;
337
			}
338
		}
339
340
		// commit
341
		$oDB->commit();
342
343
		// return
344
		if(!$manual_inserted)
345
		{
346
			$this->addGrant($obj->document_srl);
347
		}
348
		$output->add('document_srl',$obj->document_srl);
349
		$output->add('category_srl',$obj->category_srl);
350
351
		return $output;
352
	}
353
354
	/**
355
	 * Update the document
356
	 * @param object $source_obj
357
	 * @param object $obj
358
	 * @param bool $manual_updated
359
	 * @return object
360
	 */
361
	function updateDocument($source_obj, $obj, $manual_updated = FALSE)
362
	{
363
		if(!$manual_updated && !checkCSRF())
364
		{
365
			return new Object(-1, 'msg_invalid_request');
366
		}
367
368
		if(!$source_obj->document_srl || !$obj->document_srl) return new Object(-1,'msg_invalied_request');
369
		if(!$obj->status && $obj->is_secret == 'Y') $obj->status = 'SECRET';
370
		if(!$obj->status) $obj->status = 'PUBLIC';
371
372
		// Call a trigger (before)
373
		$output = ModuleHandler::triggerCall('document.updateDocument', 'before', $obj);
374
		if(!$output->toBool()) return $output;
375
376
		// begin transaction
377
		$oDB = &DB::getInstance();
378
		$oDB->begin();
379
380
		$oModuleModel = getModel('module');
381
		if(!$obj->module_srl) $obj->module_srl = $source_obj->get('module_srl');
382
		$module_srl = $obj->module_srl;
383
		$document_config = $oModuleModel->getModulePartConfig('document', $module_srl);
384
		if(!$document_config)
385
		{
386
			$document_config = new stdClass();
387
		}
388
		if(!isset($document_config->use_history)) $document_config->use_history = 'N';
389
		$bUseHistory = $document_config->use_history == 'Y' || $document_config->use_history == 'Trace';
390
391
		if($bUseHistory)
392
		{
393
			$args = new stdClass;
394
			$args->history_srl = getNextSequence();
395
			$args->document_srl = $obj->document_srl;
396
			$args->module_srl = $module_srl;
397
			if($document_config->use_history == 'Y') $args->content = $source_obj->get('content');
398
			$args->nick_name = $source_obj->get('nick_name');
399
			$args->member_srl = $source_obj->get('member_srl');
400
			$args->regdate = $source_obj->get('last_update');
401
			$args->ipaddress = $source_obj->get('ipaddress');
402
			$output = executeQuery("document.insertHistory", $args);
0 ignored issues
show
Unused Code introduced by
$output 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...
403
		}
404
		else
405
		{
406
			$obj->ipaddress = $source_obj->get('ipaddress');
407
		}
408
		// List variables
409
		if($obj->comment_status) $obj->commentStatus = $obj->comment_status;
410
		if(!$obj->commentStatus) $obj->commentStatus = 'DENY';
411
		if($obj->commentStatus == 'DENY') $this->_checkCommentStatusForOldVersion($obj);
412
		if($obj->allow_trackback!='Y') $obj->allow_trackback = 'N';
413 View Code Duplication
		if($obj->homepage)
414
		{
415
			$obj->homepage = removeHackTag($obj->homepage);
416
			if(!preg_match('/^[a-z]+:\/\//i',$obj->homepage))
417
			{
418
				$obj->homepage = 'http://'.$obj->homepage;
419
			}
420
		}
421
		
422
		if($obj->notify_message != 'Y') $obj->notify_message = 'N';
423
		
424
		// can modify regdate only manager
425
                $grant = Context::get('grant');
426
		if(!$grant->manager)
427
		{
428
			unset($obj->regdate);
429
		}
430
		
431
		// Serialize the $extra_vars
432
		if(!is_string($obj->extra_vars)) $obj->extra_vars = serialize($obj->extra_vars);
433
		// Remove the columns for automatic saving
434
		unset($obj->_saved_doc_srl);
435
		unset($obj->_saved_doc_title);
436
		unset($obj->_saved_doc_content);
437
		unset($obj->_saved_doc_message);
438
439
		$oDocumentModel = getModel('document');
440
		// Set the category_srl to 0 if the changed category is not exsiting.
441
		if($source_obj->get('category_srl')!=$obj->category_srl)
442
		{
443
			$category_list = $oDocumentModel->getCategoryList($obj->module_srl);
444
			if(!$category_list[$obj->category_srl]) $obj->category_srl = 0;
445
		}
446
		// Change the update order
447
		$obj->update_order = getNextSequence() * -1;
448
		// Hash the password if it exists
449
		if($obj->password)
450
		{
451
			$obj->password = getModel('member')->hashPassword($obj->password);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class ModuleObject as the method hashPassword() does only exist in the following sub-classes of ModuleObject: memberModel. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
452
		}
453
		// If an author is identical to the modifier or history is used, use the logged-in user's information.
454 View Code Duplication
		if(Context::get('is_logged'))
455
		{
456
			$logged_info = Context::get('logged_info');
457
			if($source_obj->get('member_srl')==$logged_info->member_srl)
458
			{
459
				$obj->member_srl = $logged_info->member_srl;
460
				$obj->user_name = htmlspecialchars_decode($logged_info->user_name);
461
				$obj->nick_name = htmlspecialchars_decode($logged_info->nick_name);
462
				$obj->email_address = $logged_info->email_address;
463
				$obj->homepage = $logged_info->homepage;
464
			}
465
		}
466
		// For the document written by logged-in user however no nick_name exists
467 View Code Duplication
		if($source_obj->get('member_srl')&& !$obj->nick_name)
468
		{
469
			$obj->member_srl = $source_obj->get('member_srl');
470
			$obj->user_name = $source_obj->get('user_name');
471
			$obj->nick_name = $source_obj->get('nick_name');
472
			$obj->email_address = $source_obj->get('email_address');
473
			$obj->homepage = $source_obj->get('homepage');
474
		}
475
		// If the tile is empty, extract string from the contents.
476
		settype($obj->title, "string");
477 View Code Duplication
		if($obj->title == '') $obj->title = cut_str(strip_tags($obj->content),20,'...');
478
		// If no tile extracted from the contents, leave it untitled.
479
		if($obj->title == '') $obj->title = 'Untitled';
480
		// Remove XE's own tags from the contents.
481
		$obj->content = preg_replace('!<\!--(Before|After)(Document|Comment)\(([0-9]+),([0-9]+)\)-->!is', '', $obj->content);
482 View Code Duplication
		if(Mobile::isFromMobilePhone())
483
		{
484
			if($obj->use_html != 'Y')
485
			{
486
				$obj->content = htmlspecialchars($obj->content, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
487
			}
488
			$obj->content = nl2br($obj->content);
489
		}
490
		// Change not extra vars but language code of the original document if document's lang_code is different from author's setting.
491
		if($source_obj->get('lang_code') != Context::getLangType())
492
		{
493
			// Change not extra vars but language code of the original document if document's lang_code doesn't exist.
494
			if(!$source_obj->get('lang_code'))
495
			{
496
				$lang_code_args->document_srl = $source_obj->get('document_srl');
0 ignored issues
show
Bug introduced by
The variable $lang_code_args does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
497
				$lang_code_args->lang_code = Context::getLangType();
498
				$output = executeQuery('document.updateDocumentsLangCode', $lang_code_args);
0 ignored issues
show
Unused Code introduced by
$output 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...
499
			}
500
			else
501
			{
502
				$extra_content = new stdClass;
503
				$extra_content->title = $obj->title;
504
				$extra_content->content = $obj->content;
505
506
				$document_args = new stdClass;
507
				$document_args->document_srl = $source_obj->get('document_srl');
508
				$document_output = executeQuery('document.getDocument', $document_args);
509
				$obj->title = $document_output->data->title;
510
				$obj->content = $document_output->data->content;
511
			}
512
		}
513
		// Remove iframe and script if not a top adminisrator in the session.
514
		if($logged_info->is_admin != 'Y')
0 ignored issues
show
Bug introduced by
The variable $logged_info 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...
515
		{
516
			$obj->content = removeHackTag($obj->content);
517
		}
518
		// if temporary document, regdate is now setting
519
		if($source_obj->get('status') == $this->getConfigStatus('temp')) $obj->regdate = date('YmdHis');
520
521
		// Insert data into the DB
522
		$output = executeQuery('document.updateDocument', $obj);
523
		if(!$output->toBool())
524
		{
525
			$oDB->rollback();
526
			return $output;
527
		}
528
		// Remove all extra variables
529
		if(Context::get('act')!='procFileDelete')
530
		{
531
			$this->deleteDocumentExtraVars($source_obj->get('module_srl'), $obj->document_srl, null, Context::getLangType());
532
			// Insert extra variables if the document successfully inserted.
533
			$extra_keys = $oDocumentModel->getExtraKeys($obj->module_srl);
534 View Code Duplication
			if(count($extra_keys))
535
			{
536
				foreach($extra_keys as $idx => $extra_item)
537
				{
538
					$value = NULL;
539
					if(isset($obj->{'extra_vars'.$idx}))
540
					{
541
						$tmp = $obj->{'extra_vars'.$idx};
542
						if(is_array($tmp))
543
							$value = implode('|@|', $tmp);
544
						else
545
							$value = trim($tmp);
546
					}
547
					else if(isset($obj->{$extra_item->name})) $value = trim($obj->{$extra_item->name});
548
					if($value == NULL) continue;
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $value of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
549
					$this->insertDocumentExtraVar($obj->module_srl, $obj->document_srl, $idx, $value, $extra_item->eid);
550
				}
551
			}
552
			// Inert extra vars for multi-language support of title and contents.
553 View Code Duplication
			if($extra_content->title) $this->insertDocumentExtraVar($obj->module_srl, $obj->document_srl, -1, $extra_content->title, 'title_'.Context::getLangType());
0 ignored issues
show
Bug introduced by
The variable $extra_content 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...
554 View Code Duplication
			if($extra_content->content) $this->insertDocumentExtraVar($obj->module_srl, $obj->document_srl, -2, $extra_content->content, 'content_'.Context::getLangType());
555
		}
556
		// Update the category if the category_srl exists.
557
		if($source_obj->get('category_srl') != $obj->category_srl || $source_obj->get('module_srl') == $logged_info->member_srl)
558
		{
559
			if($source_obj->get('category_srl') != $obj->category_srl) $this->updateCategoryCount($obj->module_srl, $source_obj->get('category_srl'));
560
			if($obj->category_srl) $this->updateCategoryCount($obj->module_srl, $obj->category_srl);
561
		}
562
		// Call a trigger (after)
563 View Code Duplication
		if($output->toBool())
564
		{
565
			$trigger_output = ModuleHandler::triggerCall('document.updateDocument', 'after', $obj);
566
			if(!$trigger_output->toBool())
567
			{
568
				$oDB->rollback();
569
				return $trigger_output;
570
			}
571
		}
572
573
		// commit
574
		$oDB->commit();
575
		// Remove the thumbnail file
576
		FileHandler::removeDir(sprintf('files/thumbnails/%s',getNumberingPath($obj->document_srl, 3)));
577
578
		$output->add('document_srl',$obj->document_srl);
579
		//remove from cache
580
		$oCacheHandler = CacheHandler::getInstance('object');
581 View Code Duplication
		if($oCacheHandler->isSupport())
582
		{
583
			//remove document item from cache
584
			$cache_key = 'document_item:'. getNumberingPath($obj->document_srl) . $obj->document_srl;
585
			$oCacheHandler->delete($cache_key);
586
		}
587
588
		return $output;
589
	}
590
591
	/**
592
	 * Deleting Documents
593
	 * @param int $document_srl
594
	 * @param bool $is_admin
595
	 * @param bool $isEmptyTrash
596
	 * @param documentItem $oDocument
597
	 * @return object
598
	 */
599
	function deleteDocument($document_srl, $is_admin = false, $isEmptyTrash = false, $oDocument = null)
600
	{
601
		// Call a trigger (before)
602
		$trigger_obj = new stdClass();
603
		$trigger_obj->document_srl = $document_srl;
604
		$output = ModuleHandler::triggerCall('document.deleteDocument', 'before', $trigger_obj);
605
		if(!$output->toBool()) return $output;
606
607
		// begin transaction
608
		$oDB = &DB::getInstance();
609
		$oDB->begin();
610
611
		if(!$isEmptyTrash)
612
		{
613
			// get model object of the document
614
			$oDocumentModel = getModel('document');
615
			// Check if the documnet exists
616
			$oDocument = $oDocumentModel->getDocument($document_srl, $is_admin);
617
		}
618
		else if($isEmptyTrash && $oDocument == null) return new Object(-1, 'document is not exists');
619
620
		if(!$oDocument->isExists() || $oDocument->document_srl != $document_srl) return new Object(-1, 'msg_invalid_document');
621
		// Check if a permossion is granted
622
		if(!$oDocument->isGranted()) return new Object(-1, 'msg_not_permitted');
623
624
		//if empty trash, document already deleted, therefore document not delete
625
		$args = new stdClass();
626
		$args->document_srl = $document_srl;
627
		if(!$isEmptyTrash)
628
		{
629
			// Delete the document
630
			$output = executeQuery('document.deleteDocument', $args);
631
			if(!$output->toBool())
632
			{
633
				$oDB->rollback();
634
				return $output;
635
			}
636
		}
637
638
		$this->deleteDocumentAliasByDocument($document_srl);
639
640
		$this->deleteDocumentHistory(null, $document_srl, null);
641
		// Update category information if the category_srl exists.
642
		if($oDocument->get('category_srl')) $this->updateCategoryCount($oDocument->get('module_srl'),$oDocument->get('category_srl'));
643
		// Delete a declared list
644
		executeQuery('document.deleteDeclared', $args);
645
		// Delete extra variable
646
		$this->deleteDocumentExtraVars($oDocument->get('module_srl'), $oDocument->document_srl);
647
648
		//this
649
		// Call a trigger (after)
650 View Code Duplication
		if($output->toBool())
651
		{
652
			$trigger_obj = $oDocument->getObjectVars();
653
			$trigger_output = ModuleHandler::triggerCall('document.deleteDocument', 'after', $trigger_obj);
654
			if(!$trigger_output->toBool())
655
			{
656
				$oDB->rollback();
657
				return $trigger_output;
658
			}
659
		}
660
		// declared document, log delete
661
		$this->_deleteDeclaredDocuments($args);
0 ignored issues
show
Documentation introduced by
$args is of type object<stdClass>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
662
		$this->_deleteDocumentReadedLog($args);
0 ignored issues
show
Documentation introduced by
$args is of type object<stdClass>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
663
		$this->_deleteDocumentVotedLog($args);
0 ignored issues
show
Documentation introduced by
$args is of type object<stdClass>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
664
665
		// Remove the thumbnail file
666
		FileHandler::removeDir(sprintf('files/thumbnails/%s',getNumberingPath($document_srl, 3)));
667
668
		// commit
669
		$oDB->commit();
670
671
		//remove from cache
672
		$oCacheHandler = CacheHandler::getInstance('object');
673
		if($oCacheHandler->isSupport())
674
		{
675
			$cache_key = 'document_item:'. getNumberingPath($document_srl) . $document_srl;
676
			$oCacheHandler->delete($cache_key);
677
		}
678
679
		return $output;
680
	}
681
682
	/**
683
	 * Delete declared document, log
684
	 * @param string $documentSrls (ex: 1, 2,56, 88)
685
	 * @return void
686
	 */
687
	function _deleteDeclaredDocuments($documentSrls)
688
	{
689
		executeQuery('document.deleteDeclaredDocuments', $documentSrls);
0 ignored issues
show
Documentation introduced by
$documentSrls is of type string, but the function expects a object|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
690
		executeQuery('document.deleteDocumentDeclaredLog', $documentSrls);
0 ignored issues
show
Documentation introduced by
$documentSrls is of type string, but the function expects a object|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
691
	}
692
693
	/**
694
	 * Delete readed log
695
	 * @param string $documentSrls (ex: 1, 2,56, 88)
696
	 * @return void
697
	 */
698
	function _deleteDocumentReadedLog($documentSrls)
699
	{
700
		executeQuery('document.deleteDocumentReadedLog', $documentSrls);
0 ignored issues
show
Documentation introduced by
$documentSrls is of type string, but the function expects a object|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
701
	}
702
703
	/**
704
	 * Delete voted log
705
	 * @param string $documentSrls (ex: 1, 2,56, 88)
706
	 * @return void
707
	 */
708
	function _deleteDocumentVotedLog($documentSrls)
709
	{
710
		executeQuery('document.deleteDocumentVotedLog', $documentSrls);
0 ignored issues
show
Documentation introduced by
$documentSrls is of type string, but the function expects a object|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
711
	}
712
713
	/**
714
	 * Move the doc into the trash
715
	 * @param object $obj
716
	 * @return object
717
	 */
718
	function moveDocumentToTrash($obj)
719
	{
720
		$trash_args = new stdClass();
721
		// Get trash_srl if a given trash_srl doesn't exist
722
		if(!$obj->trash_srl) $trash_args->trash_srl = getNextSequence();
723
		else $trash_args->trash_srl = $obj->trash_srl;
724
		// Get its module_srl which the document belongs to
725
		$oDocumentModel = getModel('document');
726
		$oDocument = $oDocumentModel->getDocument($obj->document_srl);
727
728
		$trash_args->module_srl = $oDocument->get('module_srl');
729
		$obj->module_srl = $oDocument->get('module_srl');
730
		// Cannot throw data from the trash to the trash
731
		if($trash_args->module_srl == 0) return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by documentController::moveDocumentToTrash of type object.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
732
		// Data setting
733
		$trash_args->document_srl = $obj->document_srl;
734
		$trash_args->description = $obj->description;
735
		// Insert member's information only if the member is logged-in and not manually registered.
736
		if(Context::get('is_logged')&&!$manual_inserted)
0 ignored issues
show
Bug introduced by
The variable $manual_inserted does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
737
		{
738
			$logged_info = Context::get('logged_info');
739
			$trash_args->member_srl = $logged_info->member_srl;
740
741
			// user_id, user_name and nick_name already encoded
742
			$trash_args->user_id = htmlspecialchars_decode($logged_info->user_id);
743
			$trash_args->user_name = htmlspecialchars_decode($logged_info->user_name);
744
			$trash_args->nick_name = htmlspecialchars_decode($logged_info->nick_name);
745
		}
746
		// Date setting for updating documents
747
		$document_args = new stdClass;
748
		$document_args->module_srl = 0;
749
		$document_args->document_srl = $obj->document_srl;
750
751
		// begin transaction
752
		$oDB = &DB::getInstance();
753
		$oDB->begin();
754
755
		/*$output = executeQuery('document.insertTrash', $trash_args);
756
		  if (!$output->toBool()) {
757
		  $oDB->rollback();
758
		  return $output;
759
		  }*/
760
761
		// new trash module
762
		require_once(_XE_PATH_.'modules/trash/model/TrashVO.php');
763
		$oTrashVO = new TrashVO();
764
		$oTrashVO->setTrashSrl(getNextSequence());
765
		$oTrashVO->setTitle($oDocument->variables['title']);
766
		$oTrashVO->setOriginModule('document');
767
		$oTrashVO->setSerializedObject(serialize($oDocument->variables));
768
		$oTrashVO->setDescription($obj->description);
769
770
		$oTrashAdminController = getAdminController('trash');
771
		$output = $oTrashAdminController->insertTrash($oTrashVO);
772
		if(!$output->toBool())
773
		{
774
			$oDB->rollback();
775
			return $output;
776
		}
777
778
		$output = executeQuery('document.deleteDocument', $trash_args);
779
		if(!$output->toBool())
780
		{
781
			$oDB->rollback();
782
			return $output;
783
		}
784
785
		/*$output = executeQuery('document.updateDocument', $document_args);
786
		  if (!$output->toBool()) {
787
		  $oDB->rollback();
788
		  return $output;
789
		  }*/
790
791
		// update category
792
		if($oDocument->get('category_srl')) $this->updateCategoryCount($oDocument->get('module_srl'),$oDocument->get('category_srl'));
793
794
		// remove thumbnails
795
		FileHandler::removeDir(sprintf('files/thumbnails/%s',getNumberingPath($obj->document_srl, 3)));
796
		// Set the attachment to be invalid state
797 View Code Duplication
		if($oDocument->hasUploadedFiles())
798
		{
799
			$args = new stdClass();
800
			$args->upload_target_srl = $oDocument->document_srl;
801
			$args->isvalid = 'N';
802
			executeQuery('file.updateFileValid', $args);
803
		}
804
		// Call a trigger (after)
805 View Code Duplication
		if($output->toBool())
806
		{
807
			$trigger_output = ModuleHandler::triggerCall('document.moveDocumentToTrash', 'after', $obj);
808
			if(!$trigger_output->toBool())
809
			{
810
				$oDB->rollback();
811
				return $trigger_output;
812
			}
813
		}
814
815
		// commit
816
		$oDB->commit();
817
818
		// Clear cache
819
		$oCacheHandler = CacheHandler::getInstance('object');
820 View Code Duplication
		if($oCacheHandler->isSupport())
821
		{
822
			$cache_key = 'document_item:'. getNumberingPath($oDocument->document_srl) . $oDocument->document_srl;
823
			$oCacheHandler->delete($cache_key);
824
		}
825
826
		return $output;
827
	}
828
829
	/**
830
	 * Update read counts of the document
831
	 * @param documentItem $oDocument
832
	 * @return bool|void
833
	 */
834
	function updateReadedCount(&$oDocument)
835
	{
836
		// Pass if Crawler access
837
		if(isCrawler()) return false;
838
		
839
		$document_srl = $oDocument->document_srl;
0 ignored issues
show
Bug introduced by
The property document_srl cannot be accessed from this context as it is declared private in class documentItem.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
840
		$member_srl = $oDocument->get('member_srl');
841
		$logged_info = Context::get('logged_info');
842
843
		// Call a trigger when the read count is updated (before)
844
		$trigger_output = ModuleHandler::triggerCall('document.updateReadedCount', 'before', $oDocument);
845
		if(!$trigger_output->toBool()) return $trigger_output;
846
847
		// Pass if read count is increaded on the session information
848
		if($_SESSION['readed_document'][$document_srl]) return false;
849
850
		// Pass if the author's IP address is as same as visitor's.
851
		if($oDocument->get('ipaddress') == $_SERVER['REMOTE_ADDR'])
852
		{
853
			$_SESSION['readed_document'][$document_srl] = true;
854
			return false;
855
		}
856
		// Pass ater registering sesscion if the author is a member and has same information as the currently logged-in user.
857
		if($member_srl && $logged_info->member_srl == $member_srl)
858
		{
859
			$_SESSION['readed_document'][$document_srl] = true;
860
			return false;
861
		}
862
863
		$oDB = DB::getInstance();
864
		$oDB->begin();
865
866
		// Update read counts
867
		$args = new stdClass;
868
		$args->document_srl = $document_srl;
869
		$output = executeQuery('document.updateReadedCount', $args);
0 ignored issues
show
Unused Code introduced by
$output 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...
870
871
		// Call a trigger when the read count is updated (after)
872
		$trigger_output = ModuleHandler::triggerCall('document.updateReadedCount', 'after', $oDocument);
873
		if(!$trigger_output->toBool())
874
		{
875
			$oDB->rollback();
876
			return $trigger_output;
877
		}
878
879
		$oDB->commit();
880
881
		$oCacheHandler = CacheHandler::getInstance('object');
882
		if($oCacheHandler->isSupport())
883
		{
884
			//remove document item from cache
885
			$cache_key = 'document_item:'. getNumberingPath($document_srl) . $document_srl;
886
			$oCacheHandler->delete($cache_key);
887
		}
888
889
		// Register session
890
		if(!$_SESSION['banned_document'][$document_srl]) 
891
		{
892
			$_SESSION['readed_document'][$document_srl] = true;
893
		}
894
895
		return TRUE;
896
	}
897
898
	/**
899
	 * Insert extra variables into the document table
900
	 * @param int $module_srl
901
	 * @param int $var_idx
902
	 * @param string $var_name
903
	 * @param string $var_type
904
	 * @param string $var_is_required
905
	 * @param string $var_search
906
	 * @param string $var_default
907
	 * @param string $var_desc
908
	 * @param int $eid
909
	 * @return object
910
	 */
911
	function insertDocumentExtraKey($module_srl, $var_idx, $var_name, $var_type, $var_is_required = 'N', $var_search = 'N', $var_default = '', $var_desc = '', $eid)
912
	{
913
		if(!$module_srl || !$var_idx || !$var_name || !$var_type || !$eid) return new Object(-1,'msg_invalid_request');
914
915
		$obj = new stdClass();
916
		$obj->module_srl = $module_srl;
917
		$obj->var_idx = $var_idx;
918
		$obj->var_name = $var_name;
919
		$obj->var_type = $var_type;
920
		$obj->var_is_required = $var_is_required=='Y'?'Y':'N';
921
		$obj->var_search = $var_search=='Y'?'Y':'N';
922
		$obj->var_default = $var_default;
923
		$obj->var_desc = $var_desc;
924
		$obj->eid = $eid;
925
926
		$output = executeQuery('document.getDocumentExtraKeys', $obj);
927
		if(!$output->data)
928
		{
929
			$output = executeQuery('document.insertDocumentExtraKey', $obj);
930
		}
931
		else
932
		{
933
			$output = executeQuery('document.updateDocumentExtraKey', $obj);
0 ignored issues
show
Unused Code introduced by
$output 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...
934
			// Update the extra var(eid)
935
			$output = executeQuery('document.updateDocumentExtraVar', $obj);
936
		}
937
938
		$oCacheHandler = CacheHandler::getInstance('object', NULL, TRUE);
939
		if($oCacheHandler->isSupport())
940
		{
941
			$object_key = 'module_document_extra_keys:'.$module_srl;
942
			$cache_key = $oCacheHandler->getGroupKey('site_and_module', $object_key);
943
			$oCacheHandler->delete($cache_key);
944
		}
945
946
		return $output;
947
	}
948
949
	/**
950
	 * Remove the extra variables of the documents
951
	 * @param int $module_srl
952
	 * @param int $var_idx
953
	 * @return Object
954
	 */
955
	function deleteDocumentExtraKeys($module_srl, $var_idx = null)
956
	{
957
		if(!$module_srl) return new Object(-1,'msg_invalid_request');
958
		$obj = new stdClass();
959
		$obj->module_srl = $module_srl;
960
		if(!is_null($var_idx)) $obj->var_idx = $var_idx;
961
962
		$oDB = DB::getInstance();
963
		$oDB->begin();
964
965
		$output = $oDB->executeQuery('document.deleteDocumentExtraKeys', $obj);
966
		if(!$output->toBool())
967
		{
968
			$oDB->rollback();
969
			return $output;
970
		}
971
972
		if($var_idx != NULL)
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $var_idx of type integer|null against null; this is ambiguous if the integer can be zero. Consider using a strict comparison !== instead.
Loading history...
973
		{
974
			$output = $oDB->executeQuery('document.updateDocumentExtraKeyIdxOrder', $obj);
975
			if(!$output->toBool())
976
			{
977
				$oDB->rollback();
978
				return $output;
979
			}
980
		}
981
982
		$output =  executeQuery('document.deleteDocumentExtraVars', $obj);
983
		if(!$output->toBool())
984
		{
985
			$oDB->rollback();
986
			return $output;
987
		}
988
989
		if($var_idx != NULL)
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $var_idx of type integer|null against null; this is ambiguous if the integer can be zero. Consider using a strict comparison !== instead.
Loading history...
990
		{
991
			$output = $oDB->executeQuery('document.updateDocumentExtraVarIdxOrder', $obj);
992
			if(!$output->toBool())
993
			{
994
				$oDB->rollback();
995
				return $output;
996
			}
997
		}
998
999
		$oDB->commit();
1000
1001
		$oCacheHandler = CacheHandler::getInstance('object', NULL, TRUE);
1002
		if($oCacheHandler->isSupport())
1003
		{
1004
			$object_key = 'module_document_extra_keys:'.$module_srl;
1005
			$cache_key = $oCacheHandler->getGroupKey('site_and_module', $object_key);
1006
			$oCacheHandler->delete($cache_key);
1007
		}
1008
1009
		return new Object();
1010
	}
1011
1012
	/**
1013
	 * Insert extra vaiable to the documents table
1014
	 * @param int $module_srl
1015
	 * @param int $document_srl
1016
	 * @param int $var_idx
1017
	 * @param mixed $value
1018
	 * @param int $eid
1019
	 * @param string $lang_code
1020
	 * @return Object|void
1021
	 */
1022
	function insertDocumentExtraVar($module_srl, $document_srl, $var_idx, $value, $eid = null, $lang_code = '')
1023
	{
1024
		if(!$module_srl || !$document_srl || !$var_idx || !isset($value)) return new Object(-1,'msg_invalid_request');
1025
		if(!$lang_code) $lang_code = Context::getLangType();
1026
1027
		$obj = new stdClass;
1028
		$obj->module_srl = $module_srl;
1029
		$obj->document_srl = $document_srl;
1030
		$obj->var_idx = $var_idx;
1031
		$obj->value = $value;
1032
		$obj->lang_code = $lang_code;
1033
		$obj->eid = $eid;
1034
1035
		executeQuery('document.insertDocumentExtraVar', $obj);
1036
	}
1037
1038
	/**
1039
	 * Remove values of extra variable from the document
1040
	 * @param int $module_srl
1041
	 * @param int $document_srl
1042
	 * @param int $var_idx
1043
	 * @param string $lang_code
1044
	 * @param int $eid
1045
	 * @return $output
0 ignored issues
show
Documentation introduced by
The doc-type $output could not be parsed: Unknown type name "$output" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1046
	 */
1047
	function deleteDocumentExtraVars($module_srl, $document_srl = null, $var_idx = null, $lang_code = null, $eid = null)
1048
	{
1049
		$obj = new stdClass();
1050
		$obj->module_srl = $module_srl;
1051
		if(!is_null($document_srl)) $obj->document_srl = $document_srl;
1052
		if(!is_null($var_idx)) $obj->var_idx = $var_idx;
1053
		if(!is_null($lang_code)) $obj->lang_code = $lang_code;
1054
		if(!is_null($eid)) $obj->eid = $eid;
1055
		$output = executeQuery('document.deleteDocumentExtraVars', $obj);
1056
		return $output;
1057
	}
1058
1059
1060
	/**
1061
	 * Increase the number of vote-up of the document
1062
	 * @param int $document_srl
1063
	 * @param int $point
1064
	 * @return Object
1065
	 */
1066
	function updateVotedCount($document_srl, $point = 1)
1067
	{
1068
		if($point > 0) $failed_voted = 'failed_voted';
1069
		else $failed_voted = 'failed_blamed';
1070
		// Return fail if session already has information about votes
1071
		if($_SESSION['voted_document'][$document_srl])
1072
		{
1073
			return new Object(-1, $failed_voted);
1074
		}
1075
		// Get the original document
1076
		$oDocumentModel = getModel('document');
1077
		$oDocument = $oDocumentModel->getDocument($document_srl, false, false);
1078
		// Pass if the author's IP address is as same as visitor's.
1079
		if($oDocument->get('ipaddress') == $_SERVER['REMOTE_ADDR'])
1080
		{
1081
			$_SESSION['voted_document'][$document_srl] = true;
1082
			return new Object(-1, $failed_voted);
1083
		}
1084
1085
		// Create a member model object
1086
		$oMemberModel = getModel('member');
1087
		$member_srl = $oMemberModel->getLoggedMemberSrl();
1088
1089
		// Check if document's author is a member.
1090
		if($oDocument->get('member_srl'))
1091
		{
1092
			// Pass after registering a session if author's information is same as the currently logged-in user's.
1093
			if($member_srl && $member_srl == $oDocument->get('member_srl'))
1094
			{
1095
				$_SESSION['voted_document'][$document_srl] = true;
1096
				return new Object(-1, $failed_voted);
1097
			}
1098
		}
1099
1100
		// Use member_srl for logged-in members and IP address for non-members.
1101
		$args = new stdClass;
1102
		if($member_srl)
1103
		{
1104
			$args->member_srl = $member_srl;
1105
		}
1106
		else
1107
		{
1108
			$args->ipaddress = $_SERVER['REMOTE_ADDR'];
1109
		}
1110
		$args->document_srl = $document_srl;
1111
		$output = executeQuery('document.getDocumentVotedLogInfo', $args);
1112
		// Pass after registering a session if log information has vote-up logs
1113
		if($output->data->count)
1114
		{
1115
			$_SESSION['voted_document'][$document_srl] = true;
1116
			return new Object(-1, $failed_voted);
1117
		}
1118
1119
		// begin transaction
1120
		$oDB = DB::getInstance();
1121
		$oDB->begin();
1122
1123
		// Update the voted count
1124 View Code Duplication
		if($point < 0)
1125
		{
1126
			$args->blamed_count = $oDocument->get('blamed_count') + $point;
1127
			$output = executeQuery('document.updateBlamedCount', $args);
1128
		}
1129
		else
1130
		{
1131
			$args->voted_count = $oDocument->get('voted_count') + $point;
1132
			$output = executeQuery('document.updateVotedCount', $args);
1133
		}
1134
		if(!$output->toBool()) return $output;
1135
		// Leave logs
1136
		$args->point = $point;
1137
		$output = executeQuery('document.insertDocumentVotedLog', $args);
1138
		if(!$output->toBool()) return $output;
1139
1140
		$obj = new stdClass;
1141
		$obj->member_srl = $oDocument->get('member_srl');
1142
		$obj->module_srl = $oDocument->get('module_srl');
1143
		$obj->document_srl = $oDocument->get('document_srl');
1144
		$obj->update_target = ($point < 0) ? 'blamed_count' : 'voted_count';
1145
		$obj->point = $point;
1146
		$obj->before_point = ($point < 0) ? $oDocument->get('blamed_count') : $oDocument->get('voted_count');
1147
		$obj->after_point = ($point < 0) ? $args->blamed_count : $args->voted_count;
1148
		$trigger_output = ModuleHandler::triggerCall('document.updateVotedCount', 'after', $obj);
1149
		if(!$trigger_output->toBool())
1150
		{
1151
			$oDB->rollback();
1152
			return $trigger_output;
1153
		}
1154
1155
		$oDB->commit();
1156
1157
		$oCacheHandler = CacheHandler::getInstance('object');
1158
		if($oCacheHandler->isSupport())
1159
		{
1160
			//remove document item from cache
1161
			$cache_key = 'document_item:'. getNumberingPath($document_srl) . $document_srl;
1162
			$oCacheHandler->delete($cache_key);
1163
		}
1164
1165
		// Leave in the session information
1166
		$_SESSION['voted_document'][$document_srl] = true;
1167
1168
		// Return result
1169
		$output = new Object();
1170
		if($point > 0)
1171
		{
1172
			$output->setMessage('success_voted');
1173
			$output->add('voted_count', $obj->after_point);
1174
		}
1175
		else
1176
		{
1177
			$output->setMessage('success_blamed');
1178
			$output->add('blamed_count', $obj->after_point);
1179
		}
1180
		
1181
		return $output;
1182
	}
1183
1184
	/**
1185
	 * Report posts
1186
	 * @param int $document_srl
1187
	 * @return void|Object
1188
	 */
1189
	function declaredDocument($document_srl)
1190
	{
1191
		// Fail if session information already has a reported document
1192
		if($_SESSION['declared_document'][$document_srl]) return new Object(-1, 'failed_declared');
1193
1194
		// Check if previously reported
1195
		$args = new stdClass();
1196
		$args->document_srl = $document_srl;
1197
		$output = executeQuery('document.getDeclaredDocument', $args);
1198
		if(!$output->toBool()) return $output;
1199
1200
		$declared_count = ($output->data->declared_count) ? $output->data->declared_count : 0;
1201
1202
		$trigger_obj = new stdClass();
1203
		$trigger_obj->document_srl = $document_srl;
1204
		$trigger_obj->declared_count = $declared_count;
1205
1206
		// Call a trigger (before)
1207
		$trigger_output = ModuleHandler::triggerCall('document.declaredDocument', 'before', $trigger_obj);
1208
		if(!$trigger_output->toBool())
1209
		{
1210
			return $trigger_output;
1211
		}
1212
1213
		// Get the original document
1214
		$oDocumentModel = getModel('document');
1215
		$oDocument = $oDocumentModel->getDocument($document_srl, false, false);
1216
1217
		// Pass if the author's IP address is as same as visitor's.
1218 View Code Duplication
		if($oDocument->get('ipaddress') == $_SERVER['REMOTE_ADDR']) {
1219
			$_SESSION['declared_document'][$document_srl] = true;
1220
			return new Object(-1, 'failed_declared');
1221
		}
1222
1223
		// Check if document's author is a member.
1224 View Code Duplication
		if($oDocument->get('member_srl'))
1225
		{
1226
			// Create a member model object
1227
			$oMemberModel = getModel('member');
1228
			$member_srl = $oMemberModel->getLoggedMemberSrl();
1229
			// Pass after registering a session if author's information is same as the currently logged-in user's.
1230
			if($member_srl && $member_srl == $oDocument->get('member_srl'))
1231
			{
1232
				$_SESSION['declared_document'][$document_srl] = true;
1233
				return new Object(-1, 'failed_declared');
1234
			}
1235
		}
1236
1237
		// Use member_srl for logged-in members and IP address for non-members.
1238
		$args = new stdClass;
1239
		if($member_srl)
1240
		{
1241
			$args->member_srl = $member_srl;
0 ignored issues
show
Bug introduced by
The variable $member_srl 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...
1242
		}
1243
		else
1244
		{
1245
			$args->ipaddress = $_SERVER['REMOTE_ADDR'];
1246
		}
1247
1248
		$args->document_srl = $document_srl;
1249
		$output = executeQuery('document.getDocumentDeclaredLogInfo', $args);
1250
1251
		// Pass after registering a sesson if reported/declared documents are in the logs.
1252
		if($output->data->count)
1253
		{
1254
			$_SESSION['declared_document'][$document_srl] = true;
1255
			return new Object(-1, 'failed_declared');
1256
		}
1257
1258
		// begin transaction
1259
		$oDB = &DB::getInstance();
1260
		$oDB->begin();
1261
1262
		// Add the declared document
1263
		if($declared_count > 0) $output = executeQuery('document.updateDeclaredDocument', $args);
1264
		else $output = executeQuery('document.insertDeclaredDocument', $args);
1265
		if(!$output->toBool()) return $output;
1266
		// Leave logs
1267
		$output = executeQuery('document.insertDocumentDeclaredLog', $args);
1268
		if(!$output->toBool())
1269
		{
1270
			$oDB->rollback();
1271
			return $output;
1272
		}
1273
1274
		$this->add('declared_count', $declared_count+1);
1275
1276
		// Call a trigger (after)
1277
		$trigger_obj->declared_count = $declared_count + 1;
1278
		$trigger_output = ModuleHandler::triggerCall('document.declaredDocument', 'after', $trigger_obj);
1279
		if(!$trigger_output->toBool())
1280
		{
1281
			$oDB->rollback();
1282
			return $trigger_output;
1283
		}
1284
1285
		// commit
1286
		$oDB->commit();
1287
1288
		// Leave in the session information
1289
		$_SESSION['declared_document'][$document_srl] = true;
1290
1291
		$this->setMessage('success_declared');
1292
	}
1293
1294
	/**
1295
	 * Increase the number of comments in the document
1296
	 * Update modified date, modifier, and order with increasing comment count
1297
	 * @param int $document_srl
1298
	 * @param int $comment_count
1299
	 * @param string $last_updater
1300
	 * @param bool $comment_inserted
1301
	 * @return object
1302
	 */
1303
	function updateCommentCount($document_srl, $comment_count, $last_updater, $comment_inserted = false)
1304
	{
1305
		$args = new stdClass();
1306
		$args->document_srl = $document_srl;
1307
		$args->comment_count = $comment_count;
1308
1309
		if($comment_inserted)
1310
		{
1311
			$args->update_order = -1*getNextSequence();
1312
			$args->last_updater = $last_updater;
1313
1314
			$oCacheHandler = CacheHandler::getInstance('object');
1315
			if($oCacheHandler->isSupport())
1316
			{
1317
				//remove document item from cache
1318
				$cache_key = 'document_item:'. getNumberingPath($document_srl) . $document_srl;
1319
				$oCacheHandler->delete($cache_key);
1320
			}
1321
		}
1322
1323
		return executeQuery('document.updateCommentCount', $args);
1324
	}
1325
1326
	/**
1327
	 * Increase trackback count of the document
1328
	 * @param int $document_srl
1329
	 * @param int $trackback_count
1330
	 * @return object
1331
	 */
1332
	function updateTrackbackCount($document_srl, $trackback_count)
1333
	{
1334
		$args = new stdClass;
1335
		$args->document_srl = $document_srl;
1336
		$args->trackback_count = $trackback_count;
1337
1338
		$oCacheHandler = CacheHandler::getInstance('object');
1339
		if($oCacheHandler->isSupport())
1340
		{
1341
			//remove document item from cache
1342
			$cache_key = 'document_item:'. getNumberingPath($document_srl) . $document_srl;
1343
			$oCacheHandler->delete($cache_key);
1344
		}
1345
1346
		return executeQuery('document.updateTrackbackCount', $args);
1347
	}
1348
1349
	/**
1350
	 * Add a category
1351
	 * @param object $obj
1352
	 * @return object
1353
	 */
1354
	function insertCategory($obj)
1355
	{
1356
		// Sort the order to display if a child category is added
1357
		if($obj->parent_srl)
1358
		{
1359
			// Get its parent category
1360
			$oDocumentModel = getModel('document');
1361
			$parent_category = $oDocumentModel->getCategory($obj->parent_srl);
1362
			$obj->list_order = $parent_category->list_order;
1363
			$this->updateCategoryListOrder($parent_category->module_srl, $parent_category->list_order+1);
1364
			if(!$obj->category_srl) $obj->category_srl = getNextSequence();
1365
		}
1366
		else
1367
		{
1368
			$obj->list_order = $obj->category_srl = getNextSequence();
1369
		}
1370
1371
		$output = executeQuery('document.insertCategory', $obj);
1372
		if($output->toBool())
1373
		{
1374
			$output->add('category_srl', $obj->category_srl);
1375
			$this->makeCategoryFile($obj->module_srl);
1376
		}
1377
1378
		return $output;
1379
	}
1380
1381
	/**
1382
	 * Increase list_count from a specific category
1383
	 * @param int $module_srl
1384
	 * @param int $list_order
1385
	 * @return object
1386
	 */
1387
	function updateCategoryListOrder($module_srl, $list_order)
1388
	{
1389
		$args = new stdClass;
1390
		$args->module_srl = $module_srl;
1391
		$args->list_order = $list_order;
1392
		return executeQuery('document.updateCategoryOrder', $args);
1393
	}
1394
1395
	/**
1396
	 * Update document_count in the category.
1397
	 * @param int $module_srl
1398
	 * @param int $category_srl
1399
	 * @param int $document_count
1400
	 * @return object
1401
	 */
1402
	function updateCategoryCount($module_srl, $category_srl, $document_count = 0)
1403
	{
1404
		// Create a document model object
1405
		$oDocumentModel = getModel('document');
1406
		if(!$document_count) $document_count = $oDocumentModel->getCategoryDocumentCount($module_srl,$category_srl);
1407
1408
		$args = new stdClass;
1409
		$args->category_srl = $category_srl;
1410
		$args->document_count = $document_count;
1411
		$output = executeQuery('document.updateCategoryCount', $args);
1412
		if($output->toBool()) $this->makeCategoryFile($module_srl);
1413
1414
		return $output;
1415
	}
1416
1417
	/**
1418
	 * Update category information
1419
	 * @param object $obj
1420
	 * @return object
1421
	 */
1422
	function updateCategory($obj)
1423
	{
1424
		$output = executeQuery('document.updateCategory', $obj);
1425
		if($output->toBool()) $this->makeCategoryFile($obj->module_srl);
1426
		return $output;
1427
	}
1428
1429
	/**
1430
	 * Delete a category
1431
	 * @param int $category_srl
1432
	 * @return object
1433
	 */
1434
	function deleteCategory($category_srl)
1435
	{
1436
		$args = new stdClass();
1437
		$args->category_srl = $category_srl;
1438
		$oDocumentModel = getModel('document');
1439
		$category_info = $oDocumentModel->getCategory($category_srl);
1440
		// Display an error that the category cannot be deleted if it has a child
1441
		$output = executeQuery('document.getChildCategoryCount', $args);
1442
		if(!$output->toBool()) return $output;
1443
		if($output->data->count>0) return new Object(-1, 'msg_cannot_delete_for_child');
1444
		// Delete a category information
1445
		$output = executeQuery('document.deleteCategory', $args);
1446
		if(!$output->toBool()) return $output;
1447
1448
		$this->makeCategoryFile($category_info->module_srl);
1449
		// remvove cache
1450
		$oCacheHandler = CacheHandler::getInstance('object');
1451
		if($oCacheHandler->isSupport())
1452
		{
1453
			$page = 0;
1454
			while(true) {
1455
				$args = new stdClass();
1456
				$args->category_srl = $category_srl;
1457
				$args->list_count = 100;
1458
				$args->page = ++$page;
1459
				$output = executeQuery('document.getDocumentList', $args, array('document_srl'));
1460
1461
				if($output->data == array())
1462
					break;
1463
1464
				foreach($output->data as $val)
1465
				{
1466
					//remove document item from cache
1467
					$cache_key = 'document_item:'. getNumberingPath($val->document_srl) . $val->document_srl;
1468
					$oCacheHandler->delete($cache_key);
1469
				}
1470
			}
1471
		}
1472
1473
		// Update category_srl of the documents in the same category to 0
1474
		$args = new stdClass();
1475
		$args->target_category_srl = 0;
1476
		$args->source_category_srl = $category_srl;
1477
		$output = executeQuery('document.updateDocumentCategory', $args);
1478
1479
		return $output;
1480
	}
1481
1482
	/**
1483
	 * Delete all categories in a module
1484
	 * @param int $module_srl
1485
	 * @return object
1486
	 */
1487
	function deleteModuleCategory($module_srl)
1488
	{
1489
		$args = new stdClass();
1490
		$args->module_srl = $module_srl;
1491
		$output = executeQuery('document.deleteModuleCategory', $args);
1492
		return $output;
1493
	}
1494
1495
	/**
1496
	 * Move the category level to higher
1497
	 * @param int $category_srl
1498
	 * @return Object
1499
	 */
1500
	function moveCategoryUp($category_srl)
1501
	{
1502
		$oDocumentModel = getModel('document');
1503
		// Get information of the selected category
1504
		$args = new stdClass;
1505
		$args->category_srl = $category_srl;
1506
		$output = executeQuery('document.getCategory', $args);
1507
1508
		$category = $output->data;
1509
		$list_order = $category->list_order;
1510
		$module_srl = $category->module_srl;
1511
		// Seek a full list of categories
1512
		$category_list = $oDocumentModel->getCategoryList($module_srl);
1513
		$category_srl_list = array_keys($category_list);
1514
		if(count($category_srl_list)<2) return new Object();
1515
1516
		$prev_category = NULL;
1517
		foreach($category_list as $key => $val)
1518
		{
1519
			if($key==$category_srl) break;
1520
			$prev_category = $val;
1521
		}
1522
		// Return if the previous category doesn't exist
1523
		if(!$prev_category) return new Object(-1,Context::getLang('msg_category_not_moved'));
1524
		// Return if the selected category is the top level
1525
		if($category_srl_list[0]==$category_srl) return new Object(-1,Context::getLang('msg_category_not_moved'));
1526
		// Information of the selected category
1527
		$cur_args = new stdClass;
1528
		$cur_args->category_srl = $category_srl;
1529
		$cur_args->list_order = $prev_category->list_order;
1530
		$cur_args->title = $category->title;
1531
		$this->updateCategory($cur_args);
1532
		// Category information
1533
		$prev_args = new stdClass;
1534
		$prev_args->category_srl = $prev_category->category_srl;
1535
		$prev_args->list_order = $list_order;
1536
		$prev_args->title = $prev_category->title;
1537
		$this->updateCategory($prev_args);
1538
1539
		return new Object();
1540
	}
1541
1542
	/**
1543
	 * Move the category down
1544
	 * @param int $category_srl
1545
	 * @return Object
1546
	 */
1547
	function moveCategoryDown($category_srl)
1548
	{
1549
		$oDocumentModel = getModel('document');
1550
		// Get information of the selected category
1551
		$args = new stdClass;
1552
		$args->category_srl = $category_srl;
1553
		$output = executeQuery('document.getCategory', $args);
1554
1555
		$category = $output->data;
1556
		$list_order = $category->list_order;
1557
		$module_srl = $category->module_srl;
1558
		// Seek a full list of categories
1559
		$category_list = $oDocumentModel->getCategoryList($module_srl);
1560
		$category_srl_list = array_keys($category_list);
1561
		if(count($category_srl_list)<2) return new Object();
1562
1563
		for($i=0;$i<count($category_srl_list);$i++)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
1564
		{
1565
			if($category_srl_list[$i]==$category_srl) break;
1566
		}
1567
1568
		$next_category_srl = $category_srl_list[$i+1];
1569
		if(!$category_list[$next_category_srl]) return new Object(-1,Context::getLang('msg_category_not_moved'));
1570
		$next_category = $category_list[$next_category_srl];
1571
		// Information of the selected category
1572
		$cur_args = new stdClass;
1573
		$cur_args->category_srl = $category_srl;
1574
		$cur_args->list_order = $next_category->list_order;
1575
		$cur_args->title = $category->title;
1576
		$this->updateCategory($cur_args);
1577
		// Category information
1578
		$next_args = new stdClass;
1579
		$next_args->category_srl = $next_category->category_srl;
1580
		$next_args->list_order = $list_order;
1581
		$next_args->title = $next_category->title;
1582
		$this->updateCategory($next_args);
1583
1584
		return new Object();
1585
	}
1586
1587
	/**
1588
	 * Add javascript codes into the header by checking values of document_extra_keys type, required and others
1589
	 * @param int $module_srl
1590
	 * @return void
1591
	 */
1592
	function addXmlJsFilter($module_srl)
1593
	{
1594
		$oDocumentModel = getModel('document');
1595
		$extra_keys = $oDocumentModel->getExtraKeys($module_srl);
1596
		if(!count($extra_keys)) return;
1597
1598
		$js_code = array();
1599
		$js_code[] = '<script>//<![CDATA[';
1600
		$js_code[] = '(function($){';
1601
		$js_code[] = 'var validator = xe.getApp("validator")[0];';
1602
		$js_code[] = 'if(!validator) return false;';
1603
1604
		$logged_info = Context::get('logged_info');
0 ignored issues
show
Unused Code introduced by
$logged_info 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...
1605
1606
		foreach($extra_keys as $idx => $val)
1607
		{
1608
			$idx = $val->idx;
1609
			if($val->type == 'kr_zip')
1610
			{
1611
				$idx .= '[]';
1612
			}
1613
			$name = str_ireplace(array('<script', '</script'), array('<scr" + "ipt', '</scr" + "ipt'), $val->name);
1614
			$js_code[] = sprintf('validator.cast("ADD_MESSAGE", ["extra_vars%s","%s"]);', $idx, $name);
1615
			if($val->is_required == 'Y') $js_code[] = sprintf('validator.cast("ADD_EXTRA_FIELD", ["extra_vars%s", { required:true }]);', $idx);
1616
		}
1617
1618
		$js_code[] = '})(jQuery);';
1619
		$js_code[] = '//]]></script>';
1620
		$js_code   = implode("\n", $js_code);
1621
1622
		Context::addHtmlHeader($js_code);
1623
	}
1624
1625
	/**
1626
	 * Add a category
1627
	 * @param object $args
1628
	 * @return void
1629
	 */
1630
	function procDocumentInsertCategory($args = null)
1631
	{
1632
		// List variables
1633
		if(!$args) $args = Context::gets('module_srl','category_srl','parent_srl','category_title','category_description','expand','group_srls','category_color','mid');
1634
		$args->title = $args->category_title;
1635
		$args->description = $args->category_description;
1636
		$args->color = $args->category_color;
1637
1638
		if(!$args->module_srl && $args->mid)
1639
		{
1640
			$mid = $args->mid;
0 ignored issues
show
Unused Code introduced by
$mid 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...
1641
			unset($args->mid);
1642
			$args->module_srl = $this->module_srl;
0 ignored issues
show
Bug introduced by
The property module_srl cannot be accessed from this context as it is declared private in class ModuleObject.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
1643
		}
1644
		// Check permissions
1645
		$oModuleModel = getModel('module');
1646
		$columnList = array('module_srl', 'module');
1647
		$module_info = $oModuleModel->getModuleInfoByModuleSrl($args->module_srl, $columnList);
1648
		$grant = $oModuleModel->getGrant($module_info, Context::get('logged_info'));
1649
		if(!$grant->manager) return new Object(-1,'msg_not_permitted');
1650
1651
		if($args->expand !="Y") $args->expand = "N";
1652
		if(!is_array($args->group_srls)) $args->group_srls = str_replace('|@|',',',$args->group_srls);
1653
		else $args->group_srls = implode(',', $args->group_srls);
1654
		$args->parent_srl = (int)$args->parent_srl;
1655
1656
		$oDocumentModel = getModel('document');
1657
1658
		$oDB = &DB::getInstance();
1659
		$oDB->begin();
1660
		// Check if already exists
1661
		if($args->category_srl)
1662
		{
1663
			$category_info = $oDocumentModel->getCategory($args->category_srl);
1664
			if($category_info->category_srl != $args->category_srl) $args->category_srl = null;
1665
		}
1666
		// Update if exists
1667
		if($args->category_srl)
1668
		{
1669
			$output = $this->updateCategory($args);
1670
			if(!$output->toBool())
1671
			{
1672
				$oDB->rollback();
1673
				return $output;
1674
			}
1675
			// Insert if not exist
1676
		}
1677
		else
1678
		{
1679
			$output = $this->insertCategory($args);
1680
			if(!$output->toBool())
1681
			{
1682
				$oDB->rollback();
1683
				return $output;
1684
			}
1685
		}
1686
		// Update the xml file and get its location
1687
		$xml_file = $this->makeCategoryFile($args->module_srl);
1688
1689
		$oDB->commit();
1690
1691
		$this->add('xml_file', $xml_file);
1692
		$this->add('module_srl', $args->module_srl);
1693
		$this->add('category_srl', $args->category_srl);
1694
		$this->add('parent_srl', $args->parent_srl);
1695
1696
		$returnUrl = Context::get('success_return_url') ? Context::get('success_return_url') : Context::get('error_return_url');
1697
		$this->setRedirectUrl($returnUrl);
1698
	}
1699
1700
	/**
1701
	 * Move a category
1702
	 * @return void
1703
	 */
1704
	function procDocumentMoveCategory()
1705
	{
1706
		$source_category_srl = Context::get('source_srl');
1707
		// If parent_srl exists, be the first child
1708
		$parent_category_srl = Context::get('parent_srl');
1709
		// If target_srl exists, be a sibling
1710
		$target_category_srl = Context::get('target_srl');
1711
1712
		$oDocumentModel = getModel('document');
1713
		$source_category = $oDocumentModel->getCategory($source_category_srl);
1714
		// Check permissions
1715
		$oModuleModel = getModel('module');
1716
		$columnList = array('module_srl', 'module');
1717
		$module_info = $oModuleModel->getModuleInfoByModuleSrl($source_category->module_srl, $columnList);
1718
		$grant = $oModuleModel->getGrant($module_info, Context::get('logged_info'));
1719
		if(!$grant->manager) return new Object(-1,'msg_not_permitted');
1720
1721
		// First child of the parent_category_srl
1722
		$source_args = new stdClass;
1723
		if($parent_category_srl > 0 || ($parent_category_srl == 0 && $target_category_srl == 0))
1724
		{
1725
			$parent_category = $oDocumentModel->getCategory($parent_category_srl);
0 ignored issues
show
Unused Code introduced by
$parent_category 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...
1726
1727
			$args = new stdClass;
1728
			$args->module_srl = $source_category->module_srl;
1729
			$args->parent_srl = $parent_category_srl;
1730
			$output = executeQuery('document.getChildCategoryMinListOrder', $args);
1731
1732
			if(!$output->toBool()) return $output;
1733
			$args->list_order = (int)$output->data->list_order;
1734
			if(!$args->list_order) $args->list_order = 0;
1735
			$args->list_order--;
1736
1737
			$source_args->category_srl = $source_category_srl;
1738
			$source_args->parent_srl = $parent_category_srl;
1739
			$source_args->list_order = $args->list_order;
1740
			$output = $this->updateCategory($source_args);
1741
			if(!$output->toBool()) return $output;
1742
			// Sibling of the $target_category_srl
1743
		}
1744
		else if($target_category_srl > 0)
1745
		{
1746
			$target_category = $oDocumentModel->getCategory($target_category_srl);
1747
			// Move all siblings of the $target_category down
1748
			$output = $this->updateCategoryListOrder($target_category->module_srl, $target_category->list_order+1);
1749
			if(!$output->toBool()) return $output;
1750
1751
			$source_args->category_srl = $source_category_srl;
1752
			$source_args->parent_srl = $target_category->parent_srl;
1753
			$source_args->list_order = $target_category->list_order+1;
1754
			$output = $this->updateCategory($source_args);
1755
			if(!$output->toBool()) return $output;
1756
		}
1757
		// Re-generate the xml file
1758
		$xml_file = $this->makeCategoryFile($source_category->module_srl);
1759
		// Variable settings
1760
		$this->add('xml_file', $xml_file);
1761
		$this->add('source_category_srl', $source_category_srl);
1762
	}
1763
1764
	/**
1765
	 * Delete a category
1766
	 * @return void
1767
	 */
1768
	function procDocumentDeleteCategory()
1769
	{
1770
		// List variables
1771
		$args = Context::gets('module_srl','category_srl');
1772
1773
		$oDB = &DB::getInstance();
1774
		$oDB->begin();
1775
		// Check permissions
1776
		$oModuleModel = getModel('module');
1777
		$columnList = array('module_srl', 'module');
1778
		$module_info = $oModuleModel->getModuleInfoByModuleSrl($args->module_srl, $columnList);
1779
		$grant = $oModuleModel->getGrant($module_info, Context::get('logged_info'));
1780
		if(!$grant->manager) return new Object(-1,'msg_not_permitted');
1781
1782
		$oDocumentModel = getModel('document');
1783
		// Get original information
1784
		$category_info = $oDocumentModel->getCategory($args->category_srl);
1785
		if($category_info->parent_srl) $parent_srl = $category_info->parent_srl;
1786
		// Display an error that the category cannot be deleted if it has a child node
1787
		if($oDocumentModel->getCategoryChlidCount($args->category_srl)) return new Object(-1, 'msg_cannot_delete_for_child');
1788
		// Remove from the DB
1789
		$output = $this->deleteCategory($args->category_srl);
1790
		if(!$output->toBool())
1791
		{
1792
			$oDB->rollback();
1793
			return $output;
1794
		}
1795
		// Update the xml file and get its location
1796
		$xml_file = $this->makeCategoryFile($args->module_srl);
1797
1798
		$oDB->commit();
1799
1800
		$this->add('xml_file', $xml_file);
1801
		$this->add('category_srl', $parent_srl);
0 ignored issues
show
Bug introduced by
The variable $parent_srl 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...
1802
		$this->setMessage('success_deleted');
1803
	}
1804
1805
	/**
1806
	 * Xml files updated
1807
	 * Occasionally the xml file is not generated after menu is configued on the admin page \n
1808
	 * The administrator can manually update the file in this case \n
1809
	 * Although the issue is not currently reproduced, it is unnecessay to remove.
1810
	 * @return void
1811
	 */
1812
	function procDocumentMakeXmlFile()
1813
	{
1814
		// Check input values
1815
		$module_srl = Context::get('module_srl');
1816
		// Check permissions
1817
		$oModuleModel = getModel('module');
1818
		$columnList = array('module_srl', 'module');
1819
		$module_info = $oModuleModel->getModuleInfoByModuleSrl($module_srl, $columnList);
1820
		$grant = $oModuleModel->getGrant($module_info, Context::get('logged_info'));
1821
		if(!$grant->manager) return new Object(-1,'msg_not_permitted');
1822
1823
		$xml_file = $this->makeCategoryFile($module_srl);
1824
		// Set return value
1825
		$this->add('xml_file',$xml_file);
1826
	}
1827
1828
	/**
1829
	 * Save the category in a cache file
1830
	 * @param int $module_srl
1831
	 * @return string
1832
	 */
1833
	function makeCategoryFile($module_srl)
1834
	{
1835
		// Return if there is no information you need for creating a cache file
1836
		if(!$module_srl) return false;
1837
		// Get module information (to obtain mid)
1838
		$oModuleModel = getModel('module');
1839
		$columnList = array('module_srl', 'mid', 'site_srl');
1840
		$module_info = $oModuleModel->getModuleInfoByModuleSrl($module_srl, $columnList);
1841
		$mid = $module_info->mid;
1842
1843
		if(!is_dir('./files/cache/document_category')) FileHandler::makeDir('./files/cache/document_category');
1844
		// Cache file's name
1845
		$xml_file = sprintf("./files/cache/document_category/%s.xml.php", $module_srl);
1846
		$php_file = sprintf("./files/cache/document_category/%s.php", $module_srl);
1847
		// Get a category list
1848
		$args = new stdClass();
1849
		$args->module_srl = $module_srl;
1850
		$args->sort_index = 'list_order';
1851
		$output = executeQueryArray('document.getCategoryList', $args);
1852
1853
		$category_list = $output->data;
1854
1855
		if(!is_array($category_list)) $category_list = array($category_list);
1856
1857
		$category_count = count($category_list);
1858
		for($i=0;$i<$category_count;$i++)
1859
		{
1860
			$category_srl = $category_list[$i]->category_srl;
1861
			if(!preg_match('/^[0-9,]+$/', $category_list[$i]->group_srls)) $category_list[$i]->group_srls = '';
1862
			$list[$category_srl] = $category_list[$i];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$list was never initialized. Although not strictly required by PHP, it is generally a good practice to add $list = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1863
		}
1864
		// Create the xml file without node data if no data is obtained
1865 View Code Duplication
		if(!$list)
0 ignored issues
show
Bug introduced by
The variable $list 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...
Bug Best Practice introduced by
The expression $list of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1866
		{
1867
			$xml_buff = "<root />";
1868
			FileHandler::writeFile($xml_file, $xml_buff);
1869
			FileHandler::writeFile($php_file, '<?php if(!defined("__XE__")) exit(); ?>');
1870
			return $xml_file;
1871
		}
1872
		// Change to an array if only a single data is obtained
1873
		if(!is_array($list)) $list = array($list);
1874
		// Create a tree for loop
1875
		foreach($list as $category_srl => $node)
1876
		{
1877
			$node->mid = $mid;
1878
			$parent_srl = (int)$node->parent_srl;
1879
			$tree[$parent_srl][$category_srl] = $node;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$tree was never initialized. Although not strictly required by PHP, it is generally a good practice to add $tree = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1880
		}
1881
		// A common header to set permissions and groups of the cache file
1882
		$header_script =
1883
			'$lang_type = Context::getLangType(); '.
1884
			'$is_logged = Context::get(\'is_logged\'); '.
1885
			'$logged_info = Context::get(\'logged_info\'); '.
1886
			'if($is_logged) {'.
1887
			'if($logged_info->is_admin=="Y") $is_admin = true; '.
1888
			'else $is_admin = false; '.
1889
			'$group_srls = array_keys($logged_info->group_list); '.
1890
			'} else { '.
1891
			'$is_admin = false; '.
1892
			'$group_srsl = array(); '.
1893
			'} '."\n";
1894
1895
		// Create the xml cache file (a separate session is needed for xml cache)
1896
		$xml_header_buff = '';
1897
		$xml_body_buff = $this->getXmlTree($tree[0], $tree, $module_info->site_srl, $xml_header_buff);
0 ignored issues
show
Bug introduced by
The variable $tree 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...
1898
		$xml_buff = sprintf(
1899
			'<?php '.
1900
			'define(\'__XE__\', true); '.
1901
			'require_once(\''.FileHandler::getRealPath('./config/config.inc.php').'\'); '.
1902
			'$oContext = &Context::getInstance(); '.
1903
			'$oContext->init(); '.
1904
			'header("Content-Type: text/xml; charset=UTF-8"); '.
1905
			'header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); '.
1906
			'header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); '.
1907
			'header("Cache-Control: no-store, no-cache, must-revalidate"); '.
1908
			'header("Cache-Control: post-check=0, pre-check=0", false); '.
1909
			'header("Pragma: no-cache"); '.
1910
			'%s'.
1911
			'%s '.
1912
			'$oContext->close();'.
1913
			'?>'.
1914
			'<root>%s</root>',
1915
			$header_script,
1916
			$xml_header_buff,
1917
			$xml_body_buff
1918
		);
1919
		// Create php cache file
1920
		$php_header_buff = '$_titles = array();';
1921
		$php_header_buff .= '$_descriptions = array();';
1922
		$php_output = $this->getPhpCacheCode($tree[0], $tree, $module_info->site_srl, $php_header_buff);
1923
		$php_buff = sprintf(
1924
			'<?php '.
1925
			'if(!defined("__XE__")) exit(); '.
1926
			'%s'.
1927
			'%s'.
1928
			'$menu = new stdClass;'.
1929
			'$menu->list = array(%s); ',
1930
			$header_script,
1931
			$php_header_buff,
1932
			$php_output['buff']
1933
		);
1934
		// Save File
1935
		FileHandler::writeFile($xml_file, $xml_buff);
1936
		FileHandler::writeFile($php_file, $php_buff);
1937
		return $xml_file;
1938
	}
1939
1940
	/**
1941
	 * Create the xml data recursively referring to parent_srl
1942
	 * In the menu xml file, node tag is nested and xml doc enables the admin page to have a menu\n
1943
	 * (tree menu is implemented by reading xml file from the tree_menu.js)
1944
	 * @param array $source_node
1945
	 * @param array $tree
1946
	 * @param int $site_srl
1947
	 * @param string $xml_header_buff
1948
	 * @return string
1949
	 */
1950
	function getXmlTree($source_node, $tree, $site_srl, &$xml_header_buff)
1951
	{
1952
		if(!$source_node) return;
0 ignored issues
show
Bug Best Practice introduced by
The expression $source_node of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1953
1954
		foreach($source_node as $category_srl => $node)
1955
		{
1956
			$child_buff = "";
1957
			// Get data of the child nodes
1958
			if($category_srl && $tree[$category_srl]) $child_buff = $this->getXmlTree($tree[$category_srl], $tree, $site_srl, $xml_header_buff);
1959
			// List variables
1960
			$expand = $node->expand;
1961
			$group_srls = $node->group_srls;
1962
			$mid = $node->mid;
1963
			$module_srl = $node->module_srl;
1964
			$parent_srl = $node->parent_srl;
1965
			$color = $node->color;
1966
			$description = $node->description;
1967
			// If node->group_srls value exists
1968
			if($group_srls) $group_check_code = sprintf('($is_admin==true||(is_array($group_srls)&&count(array_intersect($group_srls, array(%s)))))',$group_srls);
1969
			else $group_check_code = "true";
1970
1971
			$title = $node->title;
1972
			$oModuleAdminModel = getAdminModel('module');
1973
1974
			$langs = $oModuleAdminModel->getLangCode($site_srl, $title);
1975
			if(count($langs))
1976
			{
1977
				foreach($langs as $key => $val)
1978
				{
1979
					$xml_header_buff .= sprintf('$_titles[%d]["%s"] = "%s"; ', $category_srl, $key, str_replace('"','\\"',htmlspecialchars($val, ENT_COMPAT | ENT_HTML401, 'UTF-8', false)));
1980
				}
1981
			}
1982
1983
			$langx = $oModuleAdminModel->getLangCode($site_srl, $description);
1984
			if(count($langx))
1985
			{
1986
				foreach($langx as $key => $val)
1987
				{
1988
					$xml_header_buff .= sprintf('$_descriptions[%d]["%s"] = "%s"; ', $category_srl, $key, str_replace('"','\\"',htmlspecialchars($val, ENT_COMPAT | ENT_HTML401, 'UTF-8', false)));
1989
				}
1990
			}
1991
1992
			$attribute = sprintf(
1993
				'mid="%s" module_srl="%d" node_srl="%d" parent_srl="%d" category_srl="%d" text="<?php echo (%s?($_titles[%d][$lang_type]):"")?>" url="%s" expand="%s" color="%s" description="<?php echo (%s?($_descriptions[%d][$lang_type]):"")?>" document_count="%d" ',
1994
				$mid,
1995
				$module_srl,
1996
				$category_srl,
1997
				$parent_srl,
1998
				$category_srl,
1999
				$group_check_code,
2000
				$category_srl,
2001
				getUrl('','mid',$node->mid,'category',$category_srl),
2002
				$expand,
2003
				htmlspecialchars($color, ENT_COMPAT | ENT_HTML401, 'UTF-8', false),
2004
				$group_check_code,
2005
				$category_srl,
2006
				$node->document_count
2007
			);
2008
2009 View Code Duplication
			if($child_buff) $buff .= sprintf('<node %s>%s</node>', $attribute, $child_buff);
0 ignored issues
show
Bug introduced by
The variable $buff 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...
2010
			else $buff .=  sprintf('<node %s />', $attribute);
2011
		}
2012
		return $buff;
2013
	}
2014
2015
	/**
2016
	 * Change sorted nodes in an array to the php code and then return
2017
	 * When using menu on tpl, you can directly xml data. howver you may need javascrips additionally.
2018
	 * Therefore, you can configure the menu info directly from php cache file, not through DB.
2019
	 * You may include the cache in the ModuleHandler::displayContent()
2020
	 * @param array $source_node
2021
	 * @param array $tree
2022
	 * @param int $site_srl
2023
	 * @param string $php_header_buff
2024
	 * @return array
2025
	 */
2026
	function getPhpCacheCode($source_node, $tree, $site_srl, &$php_header_buff)
2027
	{
2028
		$output = array("buff"=>"", "category_srl_list"=>array());
2029
		if(!$source_node) return $output;
0 ignored issues
show
Bug Best Practice introduced by
The expression $source_node of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2030
2031
		// Set to an arraty for looping and then generate php script codes to be included
2032
		foreach($source_node as $category_srl => $node)
2033
		{
2034
			// Get data from child nodes first if exist.
2035
			if($category_srl && $tree[$category_srl]){
2036
				$child_output = $this->getPhpCacheCode($tree[$category_srl], $tree, $site_srl, $php_header_buff);
2037
			} else {
2038
				$child_output = array("buff"=>"", "category_srl_list"=>array());
2039
			}
2040
2041
			// Set values into category_srl_list arrary if url of the current node is not empty
2042
			$child_output['category_srl_list'][] = $node->category_srl;
2043
			$output['category_srl_list'] = array_merge($output['category_srl_list'], $child_output['category_srl_list']);
2044
2045
			// If node->group_srls value exists
2046
			if($node->group_srls) {
2047
				$group_check_code = sprintf('($is_admin==true||(is_array($group_srls)&&count(array_intersect($group_srls, array(%s)))))',$node->group_srls);
2048
			} else {
2049
				$group_check_code = "true";
2050
			}
2051
2052
			// List variables
2053
			$selected = '"' . implode('","', $child_output['category_srl_list']) . '"';
2054
			$child_buff = $child_output['buff'];
2055
			$expand = $node->expand;
2056
2057
			$title = $node->title;
2058
			$description = $node->description;
2059
			$oModuleAdminModel = getAdminModel('module');
2060
			$langs = $oModuleAdminModel->getLangCode($site_srl, $title);
2061
2062 View Code Duplication
			if(count($langs))
2063
			{
2064
				foreach($langs as $key => $val)
2065
				{
2066
					$val = htmlspecialchars($val, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
2067
					$php_header_buff .= sprintf(
2068
						'$_titles[%d]["%s"] = "%s"; ',
2069
						$category_srl,
2070
						$key,
2071
						str_replace('"','\\"', $val)
2072
					);
2073
				}
2074
			}
2075
2076
			$langx = $oModuleAdminModel->getLangCode($site_srl, $description);
2077
2078 View Code Duplication
			if(count($langx))
2079
			{
2080
				foreach($langx as $key => $val)
2081
				{
2082
					$val = htmlspecialchars($val, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
2083
					$php_header_buff .= sprintf(
2084
						'$_descriptions[%d]["%s"] = "%s"; ',
2085
						$category_srl,
2086
						$key,
2087
						str_replace('"','\\"', $val)
2088
					);
2089
				}
2090
			}
2091
2092
			// Create attributes(Use the category_srl_list to check whether to belong to the menu's node. It seems to be tricky but fast fast and powerful;)
2093
			$attribute = sprintf(
2094
				'"mid" => "%s", "module_srl" => "%d","node_srl"=>"%s","category_srl"=>"%s","parent_srl"=>"%s","text"=>$_titles[%d][$lang_type],"selected"=>(in_array(Context::get("category"),array(%s))?1:0),"expand"=>"%s","color"=>"%s","description"=>$_descriptions[%d][$lang_type],"list"=>array(%s),"document_count"=>"%d","grant"=>%s?true:false',
2095
				$node->mid,
2096
				$node->module_srl,
2097
				$node->category_srl,
2098
				$node->category_srl,
2099
				$node->parent_srl,
2100
				$node->category_srl,
2101
				$selected,
2102
				$expand,
2103
				$node->color,
2104
				$node->category_srl,
2105
				$child_buff,
2106
				$node->document_count,
2107
				$group_check_code
2108
			);
2109
2110
			// Generate buff data
2111
			$output['buff'] .=  sprintf('%s=>array(%s),', $node->category_srl, $attribute);
2112
		}
2113
2114
		return $output;
2115
	}
2116
2117
	/**
2118
	 * A method to add a pop-up menu which appears when clicking
2119
	 * @param string $url
2120
	 * @param string $str
2121
	 * @param string $icon
2122
	 * @param string $target
2123
	 * @return void
2124
	 */
2125 View Code Duplication
	function addDocumentPopupMenu($url, $str, $icon = '', $target = 'self')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2126
	{
2127
		$document_popup_menu_list = Context::get('document_popup_menu_list');
2128
		if(!is_array($document_popup_menu_list)) $document_popup_menu_list = array();
2129
2130
		$obj = new stdClass();
2131
		$obj->url = $url;
2132
		$obj->str = $str;
2133
		$obj->icon = $icon;
2134
		$obj->target = $target;
2135
		$document_popup_menu_list[] = $obj;
2136
2137
		Context::set('document_popup_menu_list', $document_popup_menu_list);
0 ignored issues
show
Documentation introduced by
$document_popup_menu_list is of type array<integer,object<stdClass>>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
2138
	}
2139
2140
	/**
2141
	 * Saved in the session when an administrator selects a post
2142
	 * @return void|Object
2143
	 */
2144
	function procDocumentAddCart()
2145
	{
2146
		if(!Context::get('is_logged')) return new Object(-1, 'msg_not_permitted');
2147
2148
		// Get document_srl
2149
		$srls = explode(',',Context::get('srls'));
2150
		for($i = 0; $i < count($srls); $i++)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
2151
		{
2152
			$srl = trim($srls[$i]);
2153
2154
			if(!$srl) continue;
2155
2156
			$document_srls[] = $srl;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$document_srls was never initialized. Although not strictly required by PHP, it is generally a good practice to add $document_srls = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
2157
		}
2158
		if(!count($document_srls)) return;
0 ignored issues
show
Bug introduced by
The variable $document_srls 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...
2159
2160
		// Get module_srl of the documents
2161
		$args = new stdClass;
2162
		$args->list_count = count($document_srls);
2163
		$args->document_srls = implode(',',$document_srls);
2164
		$args->order_type = 'asc';
2165
		$output = executeQueryArray('document.getDocuments', $args);
2166
		if(!$output->data) return new Object();
2167
2168
		unset($document_srls);
2169
		foreach($output->data as $key => $val)
2170
		{
2171
			$document_srls[$val->module_srl][] = $val->document_srl;
2172
		}
2173
		if(!$document_srls || !count($document_srls)) return new Object();
0 ignored issues
show
Bug Best Practice introduced by
The expression $document_srls of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2174
2175
		// Check if each of module administrators exists. Top-level administator will have a permission to modify every document of all modules.(Even to modify temporarily saved or trashed documents)
2176
		$oModuleModel = getModel('module');
2177
		$module_srls = array_keys($document_srls);
2178
		for($i=0;$i<count($module_srls);$i++)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
2179
		{
2180
			$module_srl = $module_srls[$i];
2181
			$module_info = $oModuleModel->getModuleInfoByModuleSrl($module_srl);
2182
			$logged_info = Context::get('logged_info');
2183
			if($logged_info->is_admin != 'Y')
2184
			{
2185
				if(!$module_info)
2186
				{
2187
					unset($document_srls[$module_srl]);
2188
					continue;
2189
				}
2190
				$grant = $oModuleModel->getGrant($module_info, $logged_info);
2191
				if(!$grant->manager)
2192
				{
2193
					unset($document_srls[$module_srl]);
2194
					continue;
2195
				}
2196
			}
2197
		}
2198
		if(!count($document_srls)) return new Object();
2199
2200
		foreach($document_srls as $module_srl => $documents)
2201
		{
2202
			$cnt = count($documents);
2203
			for($i=0;$i<$cnt;$i++)
2204
			{
2205
				$document_srl = (int)trim($documents[$i]);
2206
				if(!$document_srls) continue;
0 ignored issues
show
Bug Best Practice introduced by
The expression $document_srls of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2207
				if($_SESSION['document_management'][$document_srl]) unset($_SESSION['document_management'][$document_srl]);
2208
				else $_SESSION['document_management'][$document_srl] = true;
2209
			}
2210
		}
2211
	}
2212
2213
	/**
2214
	 * Move/ Delete the document in the seession
2215
	 * @return void|Object
2216
	 */
2217
	function procDocumentManageCheckedDocument()
2218
	{
2219
		@set_time_limit(0);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
2220
		if(!Context::get('is_logged')) return new Object(-1,'msg_not_permitted');
2221
2222
		if(!checkCSRF())
2223
		{
2224
			return new Object(-1, 'msg_invalid_request');
2225
		}
2226
2227
		$type = Context::get('type');
2228
		$target_module = Context::get('target_module');
2229
		$module_srl = Context::get('module_srl');
2230
		if($target_module && !$module_srl) $module_srl = $target_module;
2231
		$category_srl = Context::get('target_category');
2232
		$message_content = Context::get('message_content');
2233
		if($message_content) $message_content = nl2br($message_content);
2234
2235
		$cart = Context::get('cart');
2236
		if(!is_array($cart)) $document_srl_list = explode('|@|', $cart);
2237
		else $document_srl_list = $cart;
2238
2239
		$document_srl_count = count($document_srl_list);
2240
2241
		$oDocumentModel = getModel('document');
2242
		$document_items = array();
2243
		foreach($document_srl_list as $document_srl)
2244
		{
2245
			$oDocument = $oDocumentModel->getDocument($document_srl);
2246
			$document_items[] = $oDocument;
2247
			if(!$oDocument->isGranted()) return $this->stop('msg_not_permitted');
2248
		}
2249
2250
		// Send a message
2251
		if($message_content)
2252
		{
2253
2254
			$oCommunicationController = getController('communication');
2255
2256
			$logged_info = Context::get('logged_info');
2257
2258
			$title = cut_str($message_content,10,'...');
2259
			$sender_member_srl = $logged_info->member_srl;
2260
2261
			foreach($document_items as $oDocument)
2262
			{
2263
				if(!$oDocument->get('member_srl') || $oDocument->get('member_srl')==$sender_member_srl) continue;
2264
2265
				if($type=='move') $purl = sprintf("<a href=\"%s\" onclick=\"window.open(this.href);return false;\">%s</a>", $oDocument->getPermanentUrl(), $oDocument->getPermanentUrl());
2266
				else $purl = "";
2267
				$content = sprintf("<div>%s</div><hr />%s<div style=\"font-weight:bold\">%s</div>%s",$message_content, $purl, $oDocument->getTitleText(), $oDocument->getContent(false, false, false));
2268
2269
				$oCommunicationController->sendMessage($sender_member_srl, $oDocument->get('member_srl'), $title, $content, false);
2270
			}
2271
		}
2272
		// Set a spam-filer not to be filtered to spams
2273
		$oSpamController = getController('spamfilter');
2274
		$oSpamController->setAvoidLog();
2275
2276
		$oDocumentAdminController = getAdminController('document');
2277
		if($type == 'move')
2278
		{
2279
			if(!$module_srl) return new Object(-1, 'fail_to_move');
2280
2281
			$output = $oDocumentAdminController->moveDocumentModule($document_srl_list, $module_srl, $category_srl);
2282
			if(!$output->toBool()) return new Object(-1, 'fail_to_move');
2283
2284
			$msg_code = 'success_moved';
2285
2286
		}
2287
		else if($type == 'copy')
2288
		{
2289
			if(!$module_srl) return new Object(-1, 'fail_to_move');
2290
2291
			$output = $oDocumentAdminController->copyDocumentModule($document_srl_list, $module_srl, $category_srl);
2292
			if(!$output->toBool()) return new Object(-1, 'fail_to_move');
2293
2294
			$msg_code = 'success_copied';
2295
		}
2296
		else if($type =='delete')
2297
		{
2298
			$oDB = &DB::getInstance();
2299
			$oDB->begin();
2300 View Code Duplication
			for($i=0;$i<$document_srl_count;$i++)
2301
			{
2302
				$document_srl = $document_srl_list[$i];
2303
				$output = $this->deleteDocument($document_srl, true);
2304
				if(!$output->toBool()) return new Object(-1, 'fail_to_delete');
2305
			}
2306
			$oDB->commit();
2307
			$msg_code = 'success_deleted';
2308
		}
2309
		else if($type == 'trash')
2310
		{
2311
			$args = new stdClass();
2312
			$args->description = $message_content;
2313
2314
			$oDB = &DB::getInstance();
2315
			$oDB->begin();
2316 View Code Duplication
			for($i=0;$i<$document_srl_count;$i++) {
2317
				$args->document_srl = $document_srl_list[$i];
2318
				$output = $this->moveDocumentToTrash($args);
2319
				if(!$output || !$output->toBool()) return new Object(-1, 'fail_to_trash');
2320
			}
2321
			$oDB->commit();
2322
			$msg_code = 'success_trashed';
2323
		}
2324
		else if($type == 'cancelDeclare')
2325
		{
2326
			$args->document_srl = $document_srl_list;
0 ignored issues
show
Bug introduced by
The variable $args seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
2327
			$output = executeQuery('document.deleteDeclaredDocuments', $args);
0 ignored issues
show
Bug introduced by
The variable $args seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
Unused Code introduced by
$output 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...
2328
			$msg_code = 'success_declare_canceled';
2329
		}
2330
2331
		$_SESSION['document_management'] = array();
2332
2333
		$this->setMessage($msg_code);
0 ignored issues
show
Bug introduced by
The variable $msg_code 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...
2334
2335
		$returnUrl = Context::get('success_return_url') ? Context::get('success_return_url') : getNotEncodedUrl('', 'module', 'admin', 'act', 'dispDocumentAdminList');
2336
		$this->setRedirectUrl($returnUrl);
2337
	}
2338
2339
	/**
2340
	 * Insert document module config
2341
	 * @return void
2342
	 */
2343
	function procDocumentInsertModuleConfig()
2344
	{
2345
		$module_srl = Context::get('target_module_srl');
2346 View Code Duplication
		if(preg_match('/^([0-9,]+)$/',$module_srl)) $module_srl = explode(',',$module_srl);
2347
		else $module_srl = array($module_srl);
2348
2349
		$document_config = new stdClass();
2350
		$document_config->use_history = Context::get('use_history');
2351
		if(!$document_config->use_history) $document_config->use_history = 'N';
2352
2353
		$document_config->use_vote_up = Context::get('use_vote_up');
2354
		if(!$document_config->use_vote_up) $document_config->use_vote_up = 'Y';
2355
2356
		$document_config->use_vote_down = Context::get('use_vote_down');
2357
		if(!$document_config->use_vote_down) $document_config->use_vote_down = 'Y';
2358
2359
		$document_config->use_status = Context::get('use_status');
2360
2361
		$oModuleController = getController('module');
2362 View Code Duplication
		for($i=0;$i<count($module_srl);$i++)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
2363
		{
2364
			$srl = trim($module_srl[$i]);
2365
			if(!$srl) continue;
2366
			$output = $oModuleController->insertModulePartConfig('document',$srl,$document_config);
0 ignored issues
show
Unused Code introduced by
$output 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...
2367
		}
2368
		$this->setError(-1);
2369
		$this->setMessage('success_updated', 'info');
2370
2371
		$returnUrl = Context::get('success_return_url') ? Context::get('success_return_url') : getNotEncodedUrl('', 'module', 'admin', 'act', 'dispBoardAdminContent');
2372
		$this->setRedirectUrl($returnUrl);
2373
	}
2374
2375
	/**
2376
	 * Document temporary save
2377
	 * @return void|Object
2378
	 */
2379
	function procDocumentTempSave()
2380
	{
2381
		// Check login information
2382
		if(!Context::get('is_logged')) return new Object(-1, 'msg_not_logged');
2383
		$module_info = Context::get('module_info');
2384
		$logged_info = Context::get('logged_info');
0 ignored issues
show
Unused Code introduced by
$logged_info 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...
2385
2386
		// Get form information
2387
		$obj = Context::getRequestVars();
2388
		// Change the target module to log-in information
2389
		$obj->module_srl = $module_info->module_srl;
2390
		$obj->status = $this->getConfigStatus('temp');
2391
		unset($obj->is_notice);
2392
2393
		// Extract from beginning part of contents in the guestbook
2394
		if(!$obj->title)
2395
		{
2396
			$obj->title = cut_str(strip_tags($obj->content), 20, '...');
2397
		}
2398
2399
		$oDocumentModel = getModel('document');
2400
		$oDocumentController = getController('document');
2401
		// Check if already exist geulinji
2402
		$oDocument = $oDocumentModel->getDocument($obj->document_srl, $this->grant->manager);
0 ignored issues
show
Bug introduced by
The property grant does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
2403
2404
		// Update if already exists
2405
		if($oDocument->isExists() && $oDocument->document_srl == $obj->document_srl)
2406
		{
2407
			if($oDocument->get('module_srl') != $obj->module_srl)
2408
			{
2409
				return new Object(-1, 'msg_invalid_request');
2410
			}
2411
			if(!$oDocument->isGranted())
2412
			{
2413
				return new Object(-1, 'msg_invalid_request');
2414
			}
2415
			//if exist document status is already public, use temp status can point problem
2416
			$obj->status = $oDocument->get('status');
2417
			$output = $oDocumentController->updateDocument($oDocument, $obj);
0 ignored issues
show
Unused Code introduced by
$output 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...
2418
			$msg_code = 'success_updated';
0 ignored issues
show
Unused Code introduced by
$msg_code 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...
2419
			// Otherwise, get a new
2420
		}
2421
		else
2422
		{
2423
			$output = $oDocumentController->insertDocument($obj);
2424
			$msg_code = 'success_registed';
0 ignored issues
show
Unused Code introduced by
$msg_code 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...
2425
			$obj->document_srl = $output->get('document_srl');
2426
			$oDocument = $oDocumentModel->getDocument($obj->document_srl, $this->grant->manager);
2427
		}
2428
		// Set the attachment to be invalid state
2429 View Code Duplication
		if($oDocument->hasUploadedFiles())
2430
		{
2431
			$args = new stdClass;
2432
			$args->upload_target_srl = $oDocument->document_srl;
2433
			$args->isvalid = 'N';
2434
			executeQuery('file.updateFileValid', $args);
2435
		}
2436
2437
		$this->setMessage('success_saved');
2438
		$this->add('document_srl', $obj->document_srl);
2439
	}
2440
2441
	/**
2442
	 * Return Document List for exec_xml
2443
	 * @return void|Object
2444
	 */
2445
	function procDocumentGetList()
2446
	{
2447
		if(!Context::get('is_logged')) return new Object(-1,'msg_not_permitted');
2448
		$documentSrls = Context::get('document_srls');
2449
		if($documentSrls) $documentSrlList = explode(',', $documentSrls);
2450
2451
		if(count($documentSrlList) > 0)
2452
		{
2453
			$oDocumentModel = getModel('document');
2454
			$columnList = array('document_srl', 'title', 'nick_name', 'status');
2455
			$documentList = $oDocumentModel->getDocuments($documentSrlList, $this->grant->is_admin, false, $columnList);
0 ignored issues
show
Bug introduced by
The variable $documentSrlList 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...
2456
		}
2457
		else
2458
		{
2459
			global $lang;
2460
			$documentList = array();
2461
			$this->setMessage($lang->no_documents);
2462
		}
2463
		$oSecurity = new Security($documentList);
2464
		$oSecurity->encodeHTML('..variables.');
2465
		$this->add('document_list', $documentList);
2466
	}
2467
2468
	/**
2469
	 * For old version, comment allow status check.
2470
	 * @param object $obj
2471
	 * @return void
2472
	 */
2473
	function _checkCommentStatusForOldVersion(&$obj)
2474
	{
2475
		if(!isset($obj->allow_comment)) $obj->allow_comment = 'N';
2476
		if(!isset($obj->lock_comment)) $obj->lock_comment = 'N';
2477
2478
		if($obj->allow_comment == 'Y' && $obj->lock_comment == 'N') $obj->commentStatus = 'ALLOW';
2479
		else $obj->commentStatus = 'DENY';
2480
	}
2481
2482
	/**
2483
	 * For old version, document status check.
2484
	 * @param object $obj
2485
	 * @return void
2486
	 */
2487
	function _checkDocumentStatusForOldVersion(&$obj)
2488
	{
2489
		if(!$obj->status && $obj->is_secret == 'Y') $obj->status = $this->getConfigStatus('secret');
2490
		if(!$obj->status && $obj->is_secret != 'Y') $obj->status = $this->getConfigStatus('public');
2491
	}
2492
2493
	public function updateUploaedCount($documentSrlList)
2494
	{
2495
		$oDocumentModel = getModel('document');
0 ignored issues
show
Unused Code introduced by
$oDocumentModel 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...
2496
		$oFileModel = getModel('file');
2497
2498
		if(is_array($documentSrlList))
2499
		{
2500
			$documentSrlList = array_unique($documentSrlList);
2501
			foreach($documentSrlList AS $key => $documentSrl)
2502
			{
2503
				$fileCount = $oFileModel->getFilesCount($documentSrl);
2504
				$args = new stdClass();
2505
				$args->document_srl = $documentSrl;
2506
				$args->uploaded_count = $fileCount;
2507
				executeQuery('document.updateUploadedCount', $args);
2508
			}
2509
		}
2510
	}
2511
2512
	/**
2513
	 * Copy extra keys when module copied
2514
	 * @param object $obj
2515
	 * @return void
2516
	 */
2517
	function triggerCopyModuleExtraKeys(&$obj)
2518
	{
2519
		$oDocumentModel = getModel('document');
2520
		$documentExtraKeys = $oDocumentModel->getExtraKeys($obj->originModuleSrl);
2521
2522
		if(is_array($documentExtraKeys) && is_array($obj->moduleSrlList))
2523
		{
2524
			$oDocumentController=getController('document');
2525
			foreach($obj->moduleSrlList AS $key=>$value)
2526
			{
2527 View Code Duplication
				foreach($documentExtraKeys AS $extraItem)
2528
				{
2529
					$oDocumentController->insertDocumentExtraKey($value, $extraItem->idx, $extraItem->name, $extraItem->type, $extraItem->is_required , $extraItem->search , $extraItem->default , $extraItem->desc, $extraItem->eid) ;
2530
				}
2531
			}
2532
		}
2533
	}
2534
2535 View Code Duplication
	function triggerCopyModule(&$obj)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2536
	{
2537
		$oModuleModel = getModel('module');
2538
		$documentConfig = $oModuleModel->getModulePartConfig('document', $obj->originModuleSrl);
2539
2540
		$oModuleController = getController('module');
2541
		if(is_array($obj->moduleSrlList))
2542
		{
2543
			foreach($obj->moduleSrlList AS $key=>$moduleSrl)
2544
			{
2545
				$oModuleController->insertModulePartConfig('document', $moduleSrl, $documentConfig);
2546
			}
2547
		}
2548
	}
2549
}
2550
/* End of file document.controller.php */
2551
/* Location: ./modules/document/document.controller.php */
2552