1: <?php
2: /**
3: * XOOPS Kernel Class
4: *
5: * You may not change or alter any portion of this comment or credits
6: * of supporting developers from this source code or any supporting source code
7: * which is considered copyrighted (c) material of the original comment or credit authors.
8: * This program is distributed in the hope that it will be useful,
9: * but WITHOUT ANY WARRANTY; without even the implied warranty of
10: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11: *
12: * @copyright (c) 2000-2016 XOOPS Project (www.xoops.org)
13: * @license GNU GPL 2 (https://www.gnu.org/licenses/gpl-2.0.html)
14: * @package kernel
15: * @since 2.0.0
16: */
17: defined('XOOPS_ROOT_PATH') || exit('Restricted access');
18:
19: /**
20: * A Module
21: *
22: * @package kernel
23: * @author Kazumi Ono <onokazu@xoops.org>
24: */
25: class XoopsModule extends XoopsObject
26: {
27: /**
28: *
29: * @var string
30: */
31: public $modinfo;
32: /**
33: *
34: * @var array
35: */
36: public $adminmenu;
37: /**
38: *
39: * @var array
40: */
41: public $_msg;
42:
43: //PHP 8.2 Dynamic properties deprecated
44: public $mid;
45: public $name;
46: public $version;
47: public $last_update;
48: public $weight;
49: public $isactive;
50: public $dirname;
51: public $hasmain;
52: public $hasadmin;
53: public $hassearch;
54: public $hasconfig;
55: public $hascomments;
56: // RMV-NOTIFY
57: public $hasnotification;
58:
59: /**
60: * Constructor
61: */
62: public function __construct()
63: {
64: parent::__construct();
65: $this->initVar('mid', XOBJ_DTYPE_INT, null, false);
66: $this->initVar('name', XOBJ_DTYPE_TXTBOX, null, true, 150);
67: $this->initVar('version', XOBJ_DTYPE_TXTBOX, null, false);
68: $this->initVar('last_update', XOBJ_DTYPE_INT, null, false);
69: $this->initVar('weight', XOBJ_DTYPE_INT, 0, false);
70: $this->initVar('isactive', XOBJ_DTYPE_INT, 1, false);
71: $this->initVar('dirname', XOBJ_DTYPE_OTHER, null, true);
72: $this->initVar('hasmain', XOBJ_DTYPE_INT, 0, false);
73: $this->initVar('hasadmin', XOBJ_DTYPE_INT, 0, false);
74: $this->initVar('hassearch', XOBJ_DTYPE_INT, 0, false);
75: $this->initVar('hasconfig', XOBJ_DTYPE_INT, 0, false);
76: $this->initVar('hascomments', XOBJ_DTYPE_INT, 0, false);
77: // RMV-NOTIFY
78: $this->initVar('hasnotification', XOBJ_DTYPE_INT, 0, false);
79: }
80:
81: /**
82: * Load module info
83: *
84: * @param string $dirname Directory Name
85: * @param boolean $verbose
86: */
87: public function loadInfoAsVar($dirname, $verbose = true)
88: {
89: $dirname = basename($dirname);
90: if (!isset($this->modinfo)) {
91: $this->loadInfo($dirname, $verbose);
92: }
93: $this->setVar('name', $this->modinfo['name'], true);
94: $this->setVar('version', $this->modinfo['version'], true);
95: $this->setVar('dirname', $this->modinfo['dirname'], true);
96: $hasmain = (isset($this->modinfo['hasMain']) && $this->modinfo['hasMain'] == 1) ? 1 : 0;
97: $hasadmin = (isset($this->modinfo['hasAdmin']) && $this->modinfo['hasAdmin'] == 1) ? 1 : 0;
98: $hassearch = (isset($this->modinfo['hasSearch']) && $this->modinfo['hasSearch'] == 1) ? 1 : 0;
99: $hasconfig = ((isset($this->modinfo['config']) && \is_array($this->modinfo['config'])) || !empty($this->modinfo['hasComments'])) ? 1 : 0;
100: $hascomments = (isset($this->modinfo['hasComments']) && $this->modinfo['hasComments'] == 1) ? 1 : 0;
101: // RMV-NOTIFY
102: $hasnotification = (isset($this->modinfo['hasNotification']) && $this->modinfo['hasNotification'] == 1) ? 1 : 0;
103: $this->setVar('hasmain', $hasmain);
104: $this->setVar('hasadmin', $hasadmin);
105: $this->setVar('hassearch', $hassearch);
106: $this->setVar('hasconfig', $hasconfig);
107: $this->setVar('hascomments', $hascomments);
108: // RMV-NOTIFY
109: $this->setVar('hasnotification', $hasnotification);
110: }
111:
112: /**
113: * add a message
114: *
115: * @param string $str message to add
116: * @access public
117: */
118: public function setMessage($str)
119: {
120: $this->_msg[] = trim($str);
121: }
122:
123: /**
124: * return the messages for this object as an array
125: *
126: * @return array an array of messages
127: * @access public
128: */
129: public function getMessages()
130: {
131: return $this->_msg;
132: }
133:
134: /**
135: * Set module info
136: *
137: * @param string $name
138: * @param mixed $value
139: * @return bool
140: **/
141: public function setInfo($name, $value)
142: {
143: if (empty($name)) {
144: $this->modinfo = $value;
145: } else {
146: $this->modinfo[$name] = $value;
147: }
148:
149: return true;
150: }
151:
152: /**
153: * Get module info
154: *
155: * @param string $name
156: * @return array|string Array of module information.
157: * If {@link $name} is set, returns a single module information item as string.
158: */
159: public function &getInfo($name = null)
160: {
161: if (!isset($this->modinfo)) {
162: $this->loadInfo($this->getVar('dirname'));
163: }
164: if (isset($name)) {
165: if (isset($this->modinfo[$name])) {
166: return $this->modinfo[$name];
167: }
168: $return = false;
169:
170: return $return;
171: }
172:
173: return $this->modinfo;
174: }
175:
176: /**
177: * Get status
178: *
179: * @return string
180: */
181: public function getStatus()
182: {
183: return substr(strrchr($this->getVar('version'), '-'), 1);
184: }
185:
186: /**
187: * Compares two "XOOPS-standardized" version number strings.
188: *
189: * @param string $version1
190: * @param string $version2
191: * @param string $operator
192: * @return boolean The function will return true if the relationship is the one specified by the operator, false otherwise.
193: */
194: public function versionCompare($version1 = '',$version2 = '', $operator = '<')
195: {
196: $version1 = strtolower($version1);
197: $version2 = strtolower($version2);
198: if (false !== strpos($version2, '-stable')){
199: $version2 = substr($version2, 0, strpos($version2, '-stable'));
200: }
201: if (false !== strpos($version1, '-stable')){
202: $version1 = substr($version1, 0, strpos($version1, '-stable'));
203: }
204: return version_compare($version1, $version2, $operator);
205: }
206:
207: /**
208: * Get a link to the modules main page
209: *
210: * @return string FALSE on fail
211: */
212: public function mainLink()
213: {
214: if ($this->getVar('hasmain') == 1) {
215: $ret = '<a href="' . XOOPS_URL . '/modules/' . $this->getVar('dirname') . '/">' . $this->getVar('name') . '</a>';
216:
217: return $ret;
218: }
219:
220: return false;
221: }
222:
223: /**
224: * Get links to the subpages
225: *
226: * @return string
227: */
228: public function subLink()
229: {
230: $ret = array();
231: if ($this->getInfo('sub') && \is_array($this->getInfo('sub'))) {
232: foreach ($this->getInfo('sub') as $submenu) {
233: $ret[] = array(
234: 'name' => $submenu['name'],
235: 'url' => $submenu['url']);
236: }
237: }
238:
239: return $ret;
240: }
241:
242: /**
243: * Load the admin menu for the module
244: */
245: public function loadAdminMenu()
246: {
247: $adminmenu = array();
248: if ($this->getInfo('adminmenu') && $this->getInfo('adminmenu') != '' && file_exists(XOOPS_ROOT_PATH . '/modules/' . $this->getVar('dirname') . '/' . $this->getInfo('adminmenu'))) {
249: include XOOPS_ROOT_PATH . '/modules/' . $this->getVar('dirname') . '/' . $this->getInfo('adminmenu');
250: }
251: $this->adminmenu =& $adminmenu;
252: }
253:
254: /**
255: * Get the admin menu for the module
256: *
257: * @return array
258: */
259: public function &getAdminMenu()
260: {
261: if (!isset($this->adminmenu)) {
262: $this->loadAdminMenu();
263: }
264:
265: return $this->adminmenu;
266: }
267:
268: /**
269: * Load the module info for this module
270: *
271: * @param string $dirname Module directory
272: * @param bool $verbose Give an error on fail?
273: *
274: * @return bool true if loaded
275: */
276: public function loadInfo($dirname, $verbose = true)
277: {
278: static $modVersions;
279: $dirname = basename($dirname);
280: if (isset($modVersions[$dirname])) {
281: $this->modinfo = $modVersions[$dirname];
282:
283: return true;
284: }
285: global $xoopsConfig;
286: if (file_exists($file = $GLOBALS['xoops']->path('modules/' . $dirname . '/language/' . $xoopsConfig['language'] . '/modinfo.php'))) {
287: include_once $file;
288: } elseif (file_exists($file = $GLOBALS['xoops']->path('modules/' . $dirname . '/language/english/modinfo.php'))) {
289: include_once $file;
290: }
291:
292: if (!file_exists($file = $GLOBALS['xoops']->path('modules/' . $dirname . '/xoops_version.php'))) {
293: if (false !== (bool)$verbose) {
294: echo "Module File for $dirname Not Found!";
295: }
296:
297: return false;
298: }
299: include $file;
300: $modVersions[$dirname] = $modversion;
301: $this->modinfo = $modVersions[$dirname];
302:
303: return true;
304: }
305:
306: /**
307: * Search contents within a module
308: *
309: * @param string $term
310: * @param string $andor 'AND' or 'OR'
311: * @param integer $limit
312: * @param integer $offset
313: * @param integer $userid
314: * @return mixed Search result.
315: */
316: public function search($term = '', $andor = 'AND', $limit = 0, $offset = 0, $userid = 0)
317: {
318: if ($this->getVar('hassearch') != 1) {
319: return false;
320: }
321: $search =& $this->getInfo('search');
322: if ($this->getVar('hassearch') != 1 || !isset($search['file']) || !isset($search['func']) || $search['func'] == '' || $search['file'] == '') {
323: return false;
324: }
325: if (file_exists($file = $GLOBALS['xoops']->path('modules/' . $this->getVar('dirname') . '/' . $search['file']))) {
326: include_once $file;
327: } else {
328: return false;
329: }
330: if (function_exists($search['func'])) {
331: $func = $search['func'];
332:
333: return $func($term, $andor, $limit, $offset, $userid);
334: }
335:
336: return false;
337: }
338:
339: /**
340: * Returns Class Base Variable mid
341: * @param string $format
342: * @return mixed
343: */
344: public function id($format = 'N')
345: {
346: return $this->getVar('mid', $format);
347: }
348:
349: /**
350: * Returns Class Base Variable mid
351: * @param string $format
352: * @return mixed
353: */
354: public function mid($format = '')
355: {
356: return $this->getVar('mid', $format);
357: }
358:
359: /**
360: * Returns Class Base Variable name
361: * @param string $format
362: * @return mixed
363: */
364: public function name($format = '')
365: {
366: return $this->getVar('name', $format);
367: }
368:
369: /**
370: * Returns Class Base Variable version
371: * @param string $format
372: * @return mixed
373: */
374: public function version($format = '')
375: {
376: return $this->getVar('version', $format);
377: }
378:
379: /**
380: * Returns Class Base Variable last_update
381: * @param string $format
382: * @return mixed
383: */
384: public function last_update($format = '')
385: {
386: return $this->getVar('last_update', $format);
387: }
388:
389: /**
390: * Returns Class Base Variable weight
391: * @param string $format
392: * @return mixed
393: */
394: public function weight($format = '')
395: {
396: return $this->getVar('weight', $format);
397: }
398:
399: /**
400: * Returns Class Base Variable isactive
401: * @param string $format
402: * @return mixed
403: */
404: public function isactive($format = '')
405: {
406: return $this->getVar('isactive', $format);
407: }
408:
409: /**
410: * Returns Class Base Variable dirname
411: * @param string $format
412: * @return mixed
413: */
414: public function dirname($format = '')
415: {
416: return $this->getVar('dirname', $format);
417: }
418:
419: /**
420: * Returns Class Base Variable hasmain
421: * @param string $format
422: * @return mixed
423: */
424: public function hasmain($format = '')
425: {
426: return $this->getVar('hasmain', $format);
427: }
428:
429: /**
430: * Returns Class Base Variable hasadmin
431: * @param string $format
432: * @return mixed
433: */
434: public function hasadmin($format = '')
435: {
436: return $this->getVar('hasadmin', $format);
437: }
438:
439: /**
440: * Returns Class Base Variable hassearch
441: * @param string $format
442: * @return mixed
443: */
444: public function hassearch($format = '')
445: {
446: return $this->getVar('hassearch', $format);
447: }
448:
449: /**
450: * Returns Class Base Variable hasconfig
451: * @param string $format
452: * @return mixed
453: */
454: public function hasconfig($format = '')
455: {
456: return $this->getVar('hasconfig', $format);
457: }
458:
459: /**
460: * Returns Class Base Variable hascomments
461: * @param string $format
462: * @return mixed
463: */
464: public function hascomments($format = '')
465: {
466: return $this->getVar('hascomments', $format);
467: }
468:
469: /**
470: * Returns Class Base Variable hasnotification
471: * @param string $format
472: * @return mixed
473: */
474: public function hasnotification($format = '')
475: {
476: return $this->getVar('hasnotification', $format);
477: }
478:
479: /**
480: * @param $dirname
481: *
482: * @return mixed
483: */
484: public static function getByDirname($dirname)
485: {
486: /** @var XoopsModuleHandler $modhandler */
487: $modhandler = xoops_getHandler('module');
488: $inst = $modhandler->getByDirname($dirname);
489:
490: return $inst;
491: }
492:
493: ##################### Deprecated Methods ######################
494:
495: /**#@+
496: * @deprecated
497: */
498: public function checkAccess()
499: {
500: $GLOBALS['xoopsLogger']->addDeprecated(__METHOD__ . ' is deprecated');
501:
502: return false;
503: }
504:
505: /**
506: * @param string $type
507: *
508: * @return bool
509: */
510: public function loadLanguage($type = 'main')
511: {
512: $GLOBALS['xoopsLogger']->addDeprecated(__METHOD__ . ' is deprecated');
513:
514: return false;
515: }
516:
517: /**
518: * @return bool
519: */
520: public function loadErrorMessages()
521: {
522: $GLOBALS['xoopsLogger']->addDeprecated(__METHOD__ . ' is deprecated');
523:
524: return false;
525: }
526:
527: /**
528: * @return bool
529: */
530: public function getCurrentPage()
531: {
532: $GLOBALS['xoopsLogger']->addDeprecated(__METHOD__ . ' is deprecated');
533:
534: return false;
535: }
536:
537: /**
538: * @param array $admingroups
539: * @param array $accessgroups
540: *
541: * @return bool
542: */
543: public function install($admingroups = array(), $accessgroups = array())
544: {
545: $GLOBALS['xoopsLogger']->addDeprecated(__METHOD__ . ' is deprecated');
546:
547: return false;
548: }
549:
550: /**
551: * @return bool
552: */
553: public function update()
554: {
555: $GLOBALS['xoopsLogger']->addDeprecated(__METHOD__ . ' is deprecated');
556:
557: return false;
558: }
559:
560: /**
561: * @return bool
562: */
563: public function insert()
564: {
565: $GLOBALS['xoopsLogger']->addDeprecated(__METHOD__ . ' is deprecated');
566:
567: return false;
568: }
569:
570: /**
571: * @return bool
572: */
573: public function executeSQL()
574: {
575: $GLOBALS['xoopsLogger']->addDeprecated(__METHOD__ . ' is deprecated');
576:
577: return false;
578: }
579:
580: /**
581: * @return bool
582: */
583: public function insertTemplates()
584: {
585: $GLOBALS['xoopsLogger']->addDeprecated(__METHOD__ . ' is deprecated');
586:
587: return false;
588: }
589:
590: /**
591: * @param $template
592: * @param bool $block
593: *
594: * @return bool
595: */
596: public function gettemplate($template, $block = false)
597: {
598: $GLOBALS['xoopsLogger']->addDeprecated(__METHOD__ . ' is deprecated');
599:
600: return false;
601: }
602:
603: /**
604: * @return bool
605: */
606: public function insertBlocks()
607: {
608: $GLOBALS['xoopsLogger']->addDeprecated(__METHOD__ . ' is deprecated');
609:
610: return false;
611: }
612:
613: /**
614: * @return bool
615: */
616: public function insertConfigCategories()
617: {
618: $GLOBALS['xoopsLogger']->addDeprecated(__METHOD__ . ' is deprecated');
619:
620: return false;
621: }
622:
623: /**
624: * @return bool
625: */
626: public function insertConfig()
627: {
628: $GLOBALS['xoopsLogger']->addDeprecated(__METHOD__ . ' is deprecated');
629:
630: return false;
631: }
632:
633: /**
634: * @return bool
635: */
636: public function insertProfileFields()
637: {
638: $GLOBALS['xoopsLogger']->addDeprecated(__METHOD__ . ' is deprecated');
639:
640: return false;
641: }
642:
643: /**
644: * @param $type
645: * @param int $state
646: *
647: * @return bool
648: */
649: public function executeScript($type, $state = 2)
650: {
651: $GLOBALS['xoopsLogger']->addDeprecated(__METHOD__ . ' is deprecated');
652:
653: return false;
654: }
655:
656: /**
657: * @param $groups
658: * @param $type
659: *
660: * @return bool
661: */
662: public function insertGroupPermissions($groups, $type)
663: {
664: $GLOBALS['xoopsLogger']->addDeprecated(__METHOD__ . ' is deprecated');
665:
666: return false;
667: }
668: /**#@-*/
669: }
670:
671: /**
672: * XOOPS module handler class.
673: *
674: * This class is responsible for providing data access mechanisms to the data source
675: * of XOOPS module class objects.
676: *
677: * @package kernel
678: * @author Kazumi Ono <onokazu@xoops.org>
679: * @copyright (c) 2000-2016 XOOPS Project - www.xoops.org
680: *
681: * @todo Why is this not a XoopsPersistableObjectHandler?
682: */
683: class XoopsModuleHandler extends XoopsObjectHandler
684: {
685: /**
686: * holds an array of cached module references, indexed by module id
687: *
688: * @var array
689: * @access private
690: */
691: public $_cachedModule_mid = array();
692:
693: /**
694: * holds an array of cached module references, indexed by module dirname
695: *
696: * @var array
697: * @access private
698: */
699: public $_cachedModule_dirname = array();
700:
701: /**
702: * Create a new {@link XoopsModule} object
703: *
704: * @param boolean $isNew Flag the new object as "new"
705: * @return XoopsModule
706: */
707: public function create($isNew = true)
708: {
709: $module = new XoopsModule();
710: if ($isNew) {
711: $module->setNew();
712: }
713:
714: return $module;
715: }
716:
717: /**
718: * Load a module from the database
719: *
720: * @param int $id ID of the module
721: * @return XoopsObject|false false on fail
722: */
723: public function get($id)
724: {
725: static $_cachedModule_dirname;
726: static $_cachedModule_mid;
727: $id = (int)$id;
728: $module = false;
729: if ($id > 0) {
730: if (!empty($_cachedModule_mid[$id])) {
731: return $_cachedModule_mid[$id];
732: } else {
733: $sql = 'SELECT * FROM ' . $this->db->prefix('modules') . ' WHERE mid = ' . $id;
734: $result = $this->db->query($sql);
735: if (!$this->db->isResultSet($result)) {
736: return $module;
737: }
738: $numrows = $this->db->getRowsNum($result);
739: if ($numrows == 1) {
740: $module = new XoopsModule();
741: $myrow = $this->db->fetchArray($result);
742: $module->assignVars($myrow);
743: $_cachedModule_mid[$id] = &$module;
744: $_cachedModule_dirname[$module->getVar('dirname')] = &$module;
745:
746: return $module;
747: }
748: }
749: }
750:
751: return $module;
752: }
753:
754: /**
755: * Load a module by its dirname
756: *
757: * @param string $dirname
758: * @return XoopsModule|FALSE on fail
759: */
760: public function getByDirname($dirname)
761: {
762: $dirname = basename($dirname);
763: //could not we check for spaces instead??
764: if (strpos(strtolower($dirname), ' union ')) {
765: return false;
766: }
767: static $_cachedModule_mid;
768: static $_cachedModule_dirname;
769: if (!empty($_cachedModule_dirname[$dirname])) {
770: return $_cachedModule_dirname[$dirname];
771: } else {
772: $module = false;
773: $sql = 'SELECT * FROM ' . $this->db->prefix('modules') . " WHERE dirname = '" . trim($dirname) . "'";
774: $result = $this->db->query($sql);
775: if (!$this->db->isResultSet($result)) {
776: return $module;
777: }
778: $numrows = $this->db->getRowsNum($result);
779: if ($numrows == 1) {
780: $module = new XoopsModule();
781: $myrow = $this->db->fetchArray($result);
782: $module->assignVars($myrow);
783: $_cachedModule_dirname[$dirname] =& $module;
784: $_cachedModule_mid[$module->getVar('mid')] =& $module;
785: }
786:
787: return $module;
788: }
789: }
790:
791: /**
792: * Write a module to the database
793: *
794: * @param XoopsObject|XoopsModule $module a XoopsModule object
795: *
796: * @return bool true on success, otherwise false
797: */
798: public function insert(XoopsObject $module)
799: {
800: $className = 'XoopsModule';
801: if (!($module instanceof $className)) {
802: return false;
803: }
804: if (!$module->isDirty()) {
805: return true;
806: }
807: if (!$module->cleanVars()) {
808: return false;
809: }
810: foreach ($module->cleanVars as $k => $v) {
811: ${$k} = $v;
812: }
813: if ($module->isNew()) {
814: $mid = $this->db->genId('modules_mid_seq');
815: $sql = sprintf('INSERT INTO %s (mid, name, version, last_update, weight, isactive, dirname, hasmain, hasadmin, hassearch, hasconfig, hascomments, hasnotification) VALUES (%u, %s, %s, %u, %u, %u, %s, %u, %u, %u, %u, %u, %u)', $this->db->prefix('modules'), $mid, $this->db->quoteString($name), $this->db->quoteString($version), time(), $weight, 1, $this->db->quoteString($dirname), $hasmain, $hasadmin, $hassearch, $hasconfig, $hascomments, $hasnotification);
816: } else {
817: $sql = sprintf('UPDATE %s SET name = %s, dirname = %s, version = %s, last_update = %u, weight = %u, isactive = %u, hasmain = %u, hasadmin = %u, hassearch = %u, hasconfig = %u, hascomments = %u, hasnotification = %u WHERE mid = %u', $this->db->prefix('modules'), $this->db->quoteString($name), $this->db->quoteString($dirname), $this->db->quoteString($version), time(), $weight, $isactive, $hasmain, $hasadmin, $hassearch, $hasconfig, $hascomments, $hasnotification, $mid);
818: }
819: if (!$result = $this->db->query($sql)) {
820: return false;
821: }
822: if (empty($mid)) {
823: $mid = $this->db->getInsertId();
824: }
825: $module->assignVar('mid', $mid);
826: if (!empty($this->_cachedModule_dirname[$dirname])) {
827: unset($this->_cachedModule_dirname[$dirname]);
828: }
829: if (!empty($this->_cachedModule_mid[$mid])) {
830: unset($this->_cachedModule_mid[$mid]);
831: }
832:
833: return true;
834: }
835:
836: /**
837: * Delete a module from the database
838: *
839: * @param XoopsObject|XoopsModule $module a XoopsModule object
840: *
841: * @return bool true on success, otherwise false
842: */
843: public function delete(XoopsObject $module)
844: {
845: $className = 'XoopsModule';
846: if (!($module instanceof $className)) {
847: return false;
848: }
849: $sql = sprintf('DELETE FROM %s WHERE mid = %u', $this->db->prefix('modules'), $module->getVar('mid'));
850: if (!$result = $this->db->query($sql)) {
851: return false;
852: }
853: // delete admin permissions assigned for this module
854: $sql = sprintf("DELETE FROM %s WHERE gperm_name = 'module_admin' AND gperm_itemid = %u", $this->db->prefix('group_permission'), $module->getVar('mid'));
855: $this->db->query($sql);
856: // delete read permissions assigned for this module
857: $sql = sprintf("DELETE FROM %s WHERE gperm_name = 'module_read' AND gperm_itemid = %u", $this->db->prefix('group_permission'), $module->getVar('mid'));
858: $this->db->query($sql);
859:
860: $sql = sprintf('SELECT block_id FROM %s WHERE module_id = %u', $this->db->prefix('block_module_link'), $module->getVar('mid'));
861: $result = $this->db->query($sql);
862: if ($this->db->isResultSet($result)) {
863: $block_id_arr = array();
864: /** @var array $myrow */
865: while (false !== ($myrow = $this->db->fetchArray($result))) {
866: $block_id_arr[] = $myrow['block_id'];
867: }
868: }
869: // loop through block_id_arr
870: if (isset($block_id_arr)) {
871: foreach ($block_id_arr as $i) {
872: $sql = sprintf('SELECT block_id FROM %s WHERE module_id != %u AND block_id = %u', $this->db->prefix('block_module_link'), $module->getVar('mid'), $i);
873: $result2 = $this->db->query($sql);
874: if ($this->db->isResultSet($result2)) {
875: if (0 < $this->db->getRowsNum($result2)) {
876: // this block has other entries, so delete the entry for this module
877: $sql = sprintf('DELETE FROM %s WHERE (module_id = %u) AND (block_id = %u)', $this->db->prefix('block_module_link'), $module->getVar('mid'), $i);
878: $this->db->query($sql);
879: } else {
880: // this block doesn't have other entries, so disable the block and let it show on top page only. otherwise, this block will not display anymore on block admin page!
881: $sql = sprintf('UPDATE %s SET visible = 0 WHERE bid = %u', $this->db->prefix('newblocks'), $i);
882: $this->db->query($sql);
883: $sql = sprintf('UPDATE %s SET module_id = -1 WHERE module_id = %u', $this->db->prefix('block_module_link'), $module->getVar('mid'));
884: $this->db->query($sql);
885: }
886: }
887: }
888: }
889:
890: $dirname = (string) $module->getVar('dirname');
891: $mid = (int) $module->getVar('mid');
892:
893: if (!empty($this->_cachedModule_dirname[$dirname])) {
894: unset($this->_cachedModule_dirname[$dirname]);
895: }
896: if (!empty($this->_cachedModule_mid[$mid])) {
897: unset($this->_cachedModule_mid[$mid]);
898: }
899:
900: return true;
901: }
902:
903: /**
904: * Load some modules
905: *
906: * @param CriteriaElement|CriteriaCompo $criteria {@link CriteriaElement}
907: * @param boolean $id_as_key Use the ID as key into the array
908: * @return array
909: */
910: public function getObjects(CriteriaElement $criteria = null, $id_as_key = false)
911: {
912: $ret = array();
913: $limit = $start = 0;
914: $sql = 'SELECT * FROM ' . $this->db->prefix('modules');
915: if (isset($criteria) && \method_exists($criteria, 'renderWhere')) {
916: $sql .= ' ' . $criteria->renderWhere();
917: $sql .= ' ORDER BY weight ' . $criteria->getOrder() . ', mid ASC';
918: $limit = $criteria->getLimit();
919: $start = $criteria->getStart();
920: }
921: $result = $this->db->query($sql, $limit, $start);
922: if (!$this->db->isResultSet($result)) {
923: return $ret;
924: }
925: /** @var array $myrow */
926: while (false !== ($myrow = $this->db->fetchArray($result))) {
927: $module = new XoopsModule();
928: $module->assignVars($myrow);
929: if (!$id_as_key) {
930: $ret[] =& $module;
931: } else {
932: $ret[$myrow['mid']] =& $module;
933: }
934: unset($module);
935: }
936:
937: return $ret;
938: }
939:
940: /**
941: * Count some modules
942: *
943: * @param CriteriaElement|CriteriaCompo $criteria {@link CriteriaElement}
944: * @return int
945: */
946: public function getCount(CriteriaElement $criteria = null)
947: {
948: $sql = 'SELECT COUNT(*) FROM ' . $this->db->prefix('modules');
949: if (isset($criteria) && \method_exists($criteria, 'renderWhere')) {
950: $sql .= ' ' . $criteria->renderWhere();
951: }
952: $result = $this->db->query($sql);
953: if (!$this->db->isResultSet($result)) {
954: return 0;
955: }
956: list($count) = $this->db->fetchRow($result);
957:
958: return (int)$count;
959: }
960:
961: /**
962: * returns an array of module names
963: *
964: * @param CriteriaElement $criteria
965: * @param boolean $dirname_as_key if true, array keys will be module directory names
966: * if false, array keys will be module id
967: * @return array
968: */
969: public function getList(CriteriaElement $criteria = null, $dirname_as_key = false)
970: {
971: $ret = array();
972: $modules = $this->getObjects($criteria, true);
973: foreach (array_keys($modules) as $i) {
974: if (!$dirname_as_key) {
975: $ret[$i] = $modules[$i]->getVar('name');
976: } else {
977: $ret[$modules[$i]->getVar('dirname')] = $modules[$i]->getVar('name');
978: }
979: }
980:
981: return $ret;
982: }
983: }
984: