root / trunk / administrator / components / com_comprofiler / plugin.class.php @ 17

View | Annotate | Download (115.4 KB)

1
<?php
2
/**
3
* Joomla/Mambo Community Builder : Plugin Handler
4
* @version $Id: plugin.class.php 610 2006-12-13 17:33:44Z beat $
5
* @package Community Builder
6
* @subpackage plugin.class.php
7
* @author various, JoomlaJoe and Beat
8
* @copyright (C) JoomlaJoe and Beat, www.joomlapolis.com and various
9
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU/GPL version 2
10
*/
11
12
// ensure this file is being included by a parent file
13
if ( ! ( defined( '_VALID_CB' ) || defined( '_JEXEC' ) || defined( '_VALID_MOS' ) ) ) { die( 'Direct Access to this location is not allowed.' ); }
14
15
/**
16
 * CB framework
17
 * @global CBframework $_CB_framework
18
 */
19
global $_CB_framework;
20
global $mainframe;
21
if ( defined( 'JPATH_ADMINISTRATOR' ) ) {
22
        $foundation        =        JPATH_ADMINISTRATOR . '/components/com_comprofiler/plugin.foundation.php';
23
} else {
24
        $foundation        =        $mainframe->getCfg( 'absolute_path' ) . '/administrator/components/com_comprofiler/plugin.foundation.php';
25
}
26
include_once( $foundation );
27
cbimport( 'cb.database' );
28
29
30
/** utility: adds all vars of object $src to object $obj except the variable named in array exclude Array */
31
function addVarsToClass( &$obj, $src, $excludeArray ) {
32
        foreach( get_object_vars( $src ) as $key => $val ) {
33
                if ( ! in_array( $key, $excludeArray ) ) {
34
                        $obj->$key        =        $val;
35
                }
36
        }        
37
}
38
39
class cbPluginHandler {
40
        /** @var array An array of functions in event groups */
41
        var $_events                =        null;
42
        /** @var array An array of classes and pluginids for field-types */
43
        var $_fieldTypes        =        array();
44
        /** @var array An array of classes for additional field-parameters */
45
        var $_fieldParams        =        array();
46
        /** @var array An array of classes for additional tabs-parameters */
47
        var $_tabParams        =        array();
48
        /** @var array An array of menu and status items (array) */
49
        var $_menus                        =        null;
50
        /** @var array An array of lists */
51
        var $_lists                        =        null;
52
        /** @var array An array of loaded plugins objects, index=pluginId */
53
        var $_plugins                =        array();
54
        /** @var array An array indexed by the group-name of arrays of plugin ids of the plugins already loaded containing stdClass objects of the plugin table entry */
55
        var $_pluginGroups        =        array();
56
        /** @var int Index of the plugin being loaded */
57
        var $_loading                =        null;
58
        /** @var array collection of debug data */
59
        var $debugMSG                =        array();
60
        /** @var string Error Message*/
61
        var $errorMSG                =        array();
62
        var $_iserror                =        false;
63
        var $params                        =        null;        
64
        
65
        /**
66
        * Constructor
67
        */
68
        function cbPluginHandler() {
69
                $this->_events = array();
70
        }
71
        /**
72
        * Loads all the bot files for a particular group (if group not already loaded)
73
        * @param  string   $group             The group name, relates to the sub-directory in the plugins directory
74
        * @param  mixed    $ids               array of int : ids of plugins to load. OR: string : name of class 
75
        * @param  int      $publishedStatus   if 1 (DEFAULT): load only published plugins, if 0: load all plugins including unpublished ones
76
        * @return boolean                     TRUE: load done, FALSE: no plugin loaded
77
        */
78
        function loadPluginGroup( $group, $ids = null, $publishedStatus = 1 ) {
79
                global $_CB_framework, $_CB_database;
80
81
                static $dbCache                =        null;
82
83
                $this->_iserror                =        false;
84
                $group                                =        trim( $group );
85
                if ( ( $group && ! isset( $this->_pluginGroups[$group] ) ) || ( ! $this->all_in_array_key( $ids, $this->_plugins ) ) ) {
86
87
                        $cmsAccess                =        $_CB_framework->myCmsGid();
88
89
                        if ( ! isset( $dbCache[$publishedStatus][$cmsAccess][$group] ) ) {
90
                                $where                        =        array();
91
92
                                if ( $publishedStatus == 1 ) {
93
                                        $where[]        =        'published = 1';
94
                                } else {
95
                                        $where[]        =        'published >= ' . (int) $publishedStatus;
96
                                }
97
98
                                $where[]                =        'access <= '. (int) $cmsAccess;
99
100
                                if ( $group ) {
101
                                        $where[]        =        'type = ' . $_CB_database->Quote( trim ( $group ) );
102
                                }
103
/*        
104
                                if ( ( $ids !== null ) && ( count( $ids ) > 0 ) ) {
105
                                        cbArrayToInts( $ids );
106
                                        if ( count( $ids ) == 1 ) {
107
                                                $where[]        =        'id = ' . implode( '', $ids );
108
                                        } else {
109
                                                $where[]        =        'id IN (' . implode( ',', $ids ) . ')';
110
                                        }
111
                                }
112
*/
113
                                $_CB_database->setQuery( "SELECT id, folder, element, published, type, params, CONCAT_WS('/',folder,element) AS lookup, name"
114
                                . "\n FROM #__comprofiler_plugin"
115
                                . "\n WHERE " . implode( ' AND ', $where )
116
                                . "\n ORDER BY ordering"
117
                                );
118
                                $dbCache[$publishedStatus][$cmsAccess][$group]                =        $_CB_database->loadObjectList();
119
                                if ( $dbCache[$publishedStatus][$cmsAccess][$group] === null ) {
120
                                        return false;
121
                                }
122
                        }
123
                        if ( count( $ids ) == 0 ) {
124
                                $ids                        =        null;
125
                        }
126
                        foreach ( $dbCache[$publishedStatus][$cmsAccess][$group] AS $plugin ) {
127
                                if ( ( $ids === null ) || ( ( is_array( $ids ) ? in_array( $plugin->id, $ids ) : ( $plugin->element == $ids ) ) ) ) {
128
                                        if ( ( ! isset( $this->_plugins[$plugin->id] ) ) && $this->_loadPluginFile( $plugin ) ) {
129
                                                $this->_plugins[$plugin->id]                                                        =        $plugin;
130
                                                if ( ! isset( $this->_pluginGroups[$plugin->type][$plugin->id] ) ) {
131
                                                        $this->_pluginGroups[$plugin->type][$plugin->id]        =&        $this->_plugins[$plugin->id];
132
                                                }
133
                                        }
134
                                }
135
                        }
136
                }
137
                return true;
138
        }
139
        /**
140
         * Returns array of plugins which got loaded through loadPluginGroup method for that $group
141
         * Returns empty array() if none is loaded.
142
         *
143
         * @param  string  $group
144
         * @return array           keyed array ( pluginid => plugin row ( + lookup = path to plugin files
145
         */
146
        function & getLoadedPluginGroup( $group ) {
147
                if ( isset( $this->_pluginGroups[$group] ) ) {
148
                        return $this->_pluginGroups[$group];
149
                } else {
150
                        $array        =        array();
151
                        return $array;
152
                }
153
        }
154
        /** utility: checks if all elements of array needles are in array haystack */
155
        function all_in_array($needles,$haystack) {
156
                if (is_array($needles)) {
157
                        foreach ($needles as $needle) {
158
                                if (!in_array($needle,$haystack)) return false;
159
                        }
160
                } else {
161
                        if (!in_array($needles,$haystack)) return false;
162
                }
163
                return true;
164
        }
165
        /** utility: checks if all elements of array needles are in array haystack */
166
        function all_in_array_key($needles,$haystack) {
167
                if (is_array($needles)) {
168
                        foreach ($needles as $needle) {
169
                                if (!array_key_exists($needle,$haystack)) return false;
170
                        }
171
                } else {
172
                        if (!array_key_exists($needles,$haystack)) return false;
173
                }
174
                return true;
175
        }
176
        function _setLoading( $plugin, $loading = true ) {
177
                $savePreviousPluginId                                =        $this->_loading;
178
                if ( $loading === true ) {
179
                        $this->_loading                                        =        $plugin->id;
180
                } elseif ( $loading === false) {
181
                        $this->_loading                                        =        null;
182
                } else {
183
                        $this->_loading                                        =        $loading;
184
                }
185
                return $savePreviousPluginId;
186
        }
187
        function _loadPluginFile($plugin) {
188
                global $_CB_framework, $_PLUGINS;        // $_PLUGINS is needed for the include below.
189
                
190
                $path        =        $_CB_framework->getCfg('absolute_path') . '/'. $this->getPluginRelPath( $plugin ) . '/' . $plugin->element . '.php';
191
                if ( file_exists( $path ) && is_readable( $path ) ) {
192
                        $savePreviousPluginId                        =        $this->_setLoading( $plugin, true );
193
                        require_once( $path );
194
                        $this->_setLoading( $plugin, $savePreviousPluginId );
195
                        return true;
196
                } else {
197
                        return false;
198
                }
199
        }
200
        function getPluginId( ) {
201
                global $_PLUGINS;
202
                return $_PLUGINS->_loading;
203
        }
204
        function & getPluginObject( $pluginId = null ) {
205
                global $_PLUGINS;
206
                if ( $pluginId === null ) {
207
                        $pluginId        =        $_PLUGINS->_loading;
208
                }
209
                return $_PLUGINS->_plugins[$pluginId];
210
        }
211
        function & getInstanceOfPluginClass( $class, $pluginId = null ) {
212
                global $_PLUGINS;
213
                if ( $pluginId === null ) {
214
                        $pluginId        =        $_PLUGINS->_loading;
215
                }
216
217
                if ( ! isset( $this->_plugins[$pluginId]->classInstance[$class] ) ) {
218
                        if ( ! isset( $this->_plugins[$pluginId]->classInstance ) ) {
219
                                $this->_plugins[$pluginId]->classInstance                                                =        array();
220
                        }
221
                        $this->_plugins[$pluginId]->classInstance[$class]                                        =        new $class();
222
                        $this->_plugins[$pluginId]->classInstance[$class]->_cbpluginid                =        $pluginId;
223
                }
224
225
                return $this->_plugins[$pluginId]->classInstance[$class];
226
        }
227
        /**
228
        * Gets a variable from the plugin class
229
        * @param int id of plugin
230
        * @param string name of plugin class
231
        * @param string name of class variable
232
        * @return mixed : variable's content
233
        */
234
        function getVar($pluginId, $class, $variable) {
235
                if ($class!=null && class_exists($class) && isset( $this->_plugins[$pluginId] ) ) {
236
                        if ($this->_plugins[$pluginId]->published) {
237
                                if (isset( $this->_plugins[$pluginId]->classInstance[$class]->$variable )) {
238
                                        return $this->_plugins[$pluginId]->classInstance[$class]->$variable;
239
                                } 
240
                        }
241
                }
242
                return false;
243
        }
244
        function getPluginPath() {
245
                global $_CB_framework, $_PLUGINS;
246
247
                // $plugin        =        $_PLUGINS->_pluginGroups[$this->type][$this->_cbpluginid];        //TBD: check for multiple classes per plugin ??? + getPluginCLass/vs. getTabCLass
248
                $plugin                =&        $_PLUGINS->_plugins[$this->_cbpluginid];                                        //TBD: remove those vars from here and make this function available to API
249
                return $_CB_framework->getCfg('absolute_path') . '/'. $this->getPluginRelPath( $plugin );
250
        }
251
        function getPluginRelPath( $plugin ) {
252
                if ( $plugin->folder && ( $plugin->folder[0] == '/' ) ) {
253
                        return substr( $plugin->folder, 1 );
254
                } else {
255
                        return 'components/com_comprofiler/plugin/' . $plugin->type . '/'. $plugin->folder;
256
                }
257
        }
258
        function getPluginXmlPath( $plugin ) {
259
                global $_CB_framework;
260
                return $_CB_framework->getCfg('absolute_path') . '/'. $this->getPluginRelPath( $plugin ) . '/' . $plugin->element . '.xml';
261
        }
262
        function getPluginLIvePath() {
263
                global $_CB_framework, $_PLUGINS;
264
265
                // $plugin        =        $_PLUGINS->_pluginGroups[$this->type][$this->_cbpluginid];        //TBD: check for multiple classes per plugin ??? + getPluginCLass/vs. getTabCLass
266
                $plugin                =&        $_PLUGINS->_plugins[$this->_cbpluginid];                                        //TBD: remove those vars from here and make this function available to API
267
                return $_CB_framework->getCfg('live_site') . '/'. $this->getPluginRelPath( $plugin );
268
        }
269
        function _loadParams($pluginId, $extraParams=null) {
270
                global $_PLUGINS;
271
                $this->params        =        new cbParamsBase($_PLUGINS->_plugins[$pluginId]->params . "\n" . $extraParams);        
272
        }
273
        function & getParams() {
274
                return $this->params;
275
        }
276
        function getXml( $type = null, $typeValue = null ) {
277
                return null;                // override if needed
278
        }
279
280
        /**
281
         * FIELDS PLUGINS MANAGEMENT: through $_PLUGINS only:
282
         */
283
284
        /**
285
        * Registers a field type which can be used by users
286
        *
287
        * @param array $typesArray  array of string of the names of types of fields
288
        * @param int   $pluginId    for CB internal plugin installer use ONLY: id of plugin to associate with field type
289
        */
290
        function registerUserFieldTypes( $typesArray, $pluginId = null ) {
291
                if ( $pluginId === null ) {
292
                        $pluginId                                        =        $this->_loading;
293
                }
294
                foreach ( $typesArray as $type => $class ) {
295
                        $this->_fieldTypes[$type]        =        array( $class, $pluginId );
296
                }
297
        }
298
        /**
299
         * Returns array of field types
300
         *
301
         * @return array of string  Names of types registered
302
         */
303
        function getUserFieldTypes( ) {
304
                return array_keys( $this->_fieldTypes );
305
        }
306
        /**
307
         * Returns array of field types
308
         *
309
         * @param  string $fieldType  Type of field
310
         * @return array of string    Names of types registered
311
         */
312
        function getUserFieldPluginId( $fieldType ) {
313
                if (isset( $this->_fieldTypes[$fieldType] ) ) {
314
                        return $this->_fieldTypes[$fieldType][1];
315
                }
316
                return null;
317
        }
318
        /**
319
        * Calls a function of a field type
320
        *
321
        * @param  string $fieldType  Type of field
322
        * @param  string $method     Method to call
323
        * @param  array  $args       An array of arguments
324
        * @return mixed  result of function call or NULL if non-existant
325
        */
326
        function callField( $fieldType, $method, $args = null, &$field ) {
327
                global $_PLUGINS;
328
329
                $result                                 =        null;
330
331
                if ($args === null) {
332
                        $args                                =        array();
333
                }
334
                if ( isset( $this->_fieldTypes[$fieldType] ) ) {
335
336
                        // warning: these events are completely experimental in CB 1.2 and can change !!!
337
                        $event                                =        'onBefore' . $method;
338
                        if (isset( $_PLUGINS->_events[$event] ) ) {
339
                                $result                        =        implode( '', $_PLUGINS->trigger( $event, $args ) );
340
                        }
341
342
                        if ( ! $result ) {
343
                                $result                        =        $this->call( $this->_fieldTypes[$fieldType][1], $method, $this->_fieldTypes[$fieldType][0], $args );
344
                        }
345
346
                        // warning: these events are completely experimental in CB 1.2 and can change !!!
347
                        $event                                =        'onAfter' . $method;
348
                        if (isset( $_PLUGINS->_events[$event] ) ) {
349
                                $args[]                        =&        $result;
350
                                $_PLUGINS->trigger( $event, $args );
351
                        }
352
353
                }
354
                return $result;
355
        }
356
        /**
357
        * Registers field params for fields
358
        * 
359
        * @param  $class  name of class if overriding core class cbFieldParamsHandler which then needs to be extended.
360
        */
361
        function registerUserFieldParams( $class = null ) {
362
                $pluginId                                                        =        $this->_loading;
363
                if ( $class === null ) {
364
                        $class                                                        =        'cbFieldParamsHandler';
365
                }
366
                $this->_fieldParams[$pluginId]                =        $class;
367
        }
368
        /**
369
         * Returns array of field types
370
         *
371
         * @return array of string  pluginid => Names of class
372
         */
373
        function getUserFieldParamsPluginIds( ) {
374
                return $this->_fieldParams;
375
        }
376
377
        /**
378
        * Registers tab params for fields
379
        * 
380
        * @param  $class  name of class if overriding core class cbFieldParamsHandler which then needs to be extended.
381
        */
382
        function registerUserTabParams( $class = null ) {
383
                $pluginId                                                        =        $this->_loading;
384
                if ( $class === null ) {
385
                        $class                                                        =        'cbTabParamsHandler';
386
                }
387
                $this->_tabParams[$pluginId]                =        $class;
388
        }
389
        /**
390
         * Returns array of tab types
391
         *
392
         * @return array of string  pluginid => Names of class
393
         */
394
        function getUserTabParamsPluginIds( ) {
395
                return $this->_tabParams;
396
        }
397
        /**
398
        * Calls a function of a template type
399
        *
400
        * @param  string $fieldType  Type of field
401
        * @param  string $method     Method to call
402
        * @param  array  $args       An array of arguments
403
        * @param  string $output     'html' (in future: 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist', 'htmledit')
404
        * @return mixed  result of function call or NULL if non-existant
405
        */
406
        function callTemplate( $element, $subClass, $method, $args, $output = 'html' ) {
407
                if ( $output == 'htmledit' ) {
408
                        $output                =        'html';
409
                }
410
                foreach ( array_keys( $this->_pluginGroups['templates'] ) as $pluginId ) {
411
                        if ( $this->_pluginGroups['templates'][$pluginId]->element == $element ) {
412
                                return $this->call( $pluginId, $method, 'CB'.$subClass.'View_'. $output . '_' . $element , $args );
413
                        }
414
                }
415
                return null;
416
        }
417
418
        /**
419
         * MENU MANAGEMENT:
420
         */
421
422
        /**
423
         * Adds a menu
424
         * @access private
425
         * 
426
         * @param unknown_type $menuItem
427
         */
428
        function _internalPLUGINSaddMenu( $menuItem ) {
429
                $this->_menus[]        =        $menuItem;
430
        }
431
        /**
432
        * Registers a menu or status item to a particular menu position
433
        * 
434
        * @param array a menu item like:
435
                // Test example:
436
                $mi = array(); $mi["_UE_MENU_CONNECTIONS"]["duplique"]=null;
437
                $this->addMenu( array(        "position"        => "menuBar" ,                // "menuBar", "menuList"
438
                                                                        "arrayPos"        => $mi ,
439
                                                                        "caption"        => _UE_MENU_MANAGEMYCONNECTIONS ,
440
                                                                        "url"                => cbSef($ue_manageConnection_url) ,                // can also be "<a ....>" or "javascript:void(0)" or ""
441
                                                                        "target"        => "" ,        // e.g. "_blank"
442
                                                                        "img"                => null ,        // e.g. "<img src='plugins/user/myplugin/images/icon.gif' width='16' height='16' alt='' />"
443
                                                                        "alt"                => null ,        // e.g. "text"
444
                                                                        "tooltip"        => _UE_MENU_MANAGEMYCONNECTIONS_DESC ,
445
                                                                        "keystroke"        => null ) );        // e.g. "P"
446
                // Test example: Member Since:
447
                $mi = array(); $mi["_UE_MENU_STATUS"]["_UE_MEMBERSINCE"]["dupl"]=null;
448
                $dat = cbFormatDate($user->registerDate);
449
                if (!$dat) $dat="?";
450
                $this->addMenu( array(        "position"        => "menuList" ,                // "menuBar", "menuList"
451
                                                                        "arrayPos"        => $mi ,
452
                                                                        "caption"        => $dat ,
453
                                                                        "url"                => "" ,                // can also be "<a ....>" or "javascript:void(0)" or ""
454
                                                                        "target"        => "" ,        // e.g. "_blank"
455
                                                                        "img"                => null ,        // e.g. "<img src='plugins/user/myplugin/images/icon.gif' width='16' height='16' alt='' />"
456
                                                                        "alt"                => null ,        // e.g. "text"
457
                                                                        "tooltip"        => _UE_MEMBERSINCE_DESC ,
458
                                                                        "keystroke"        => null ) );        // e.g. "P"
459
        */
460
        function addMenu( $menuItem ) {
461
                global $_PLUGINS;
462
                $_PLUGINS->_internalPLUGINSaddMenu($menuItem);
463
        }
464
        /**
465
        * Returns all menu items registered with addMenu
466
        * @param string The event name
467
        * @param string The function name
468
        */
469
        function getMenus() {
470
                return $this->_menus;
471
        }
472
473
        /**
474
         * EVENTS AND TRIGGERS METHODS:
475
         */
476
477
        /**
478
        * Registers a function to a particular event group
479
        * @param string The event name
480
        * @param string The function name
481
        */
482
        function registerFunction( $event, $method, $class=null ) {
483
                $this->_events[$event][] = array( $class,$method, $this->_loading );
484
        }
485
        /**
486
        * Calls all functions associated with an event group
487
        * @param string The event name
488
        * @param array An array of arguments
489
        * @return array An array of results from each function call
490
        */
491
        function trigger( $event, $args=null ) {
492
                $result                                =        array();
493
494
                if ($args === null) {
495
                        $args                        =        array();
496
                }
497
                if (isset( $this->_events[$event] ) ) {
498
                        foreach ($this->_events[$event] as $func) {
499
                                $result[]        =        $this->call($func[2],$func[1],$func[0],$args);
500
                        }
501
                }
502
                return $result;
503
        }
504
        function is_errors() {
505
                return $this->_iserror;
506
        }
507
        /**
508
        * Execute the plugin class/method pair
509
        * @param int id of plugin
510
        * @param string name of plugin variable
511
        * @param mixed value to assign (if any)
512
        * @return mixed : previous value
513
        */
514
        function plugVarValue($pluginid, $var, $value=null) {
515
                $preValue                                                                =        $this->_plugins[$pluginid]->$var;
516
                if ( $value !== null ) {
517
                        $this->_plugins[$pluginid]->$var        =        $value;
518
                }
519
                return $preValue;
520
        }
521
        /**
522
        * Execute the plugin class/method pair
523
        * @param $pluginid int id of plugin
524
        * @param $method string name of plugin method
525
        * @param $class string name of plugin class
526
        * @param $args array set of variables to path to class/method
527
        * @param $extraParams string additional parameters external to plugin params (e.g. tab params)
528
        * @return mixed : either string HTML for tab content, or false if ErrorMSG generated
529
        */
530
        function call( $pluginid, $method, $class, &$args, $extraParams = null, $ignorePublishedStatus = false ) {
531
                if ( $class != null && class_exists( $class ) ) {
532
                        if ( $this->_plugins[$pluginid]->published || $ignorePublishedStatus ) {
533
534
                                $pluginClassInstance                                =&        $this->getInstanceOfPluginClass( $class, $pluginid );
535
                                if (method_exists( $pluginClassInstance, $method )) {
536
                                        $pluginClassInstance->_loadParams( $pluginid, $extraParams );
537
//BB1.2b7: really needed to have plugin row in tab and field classes called ???        element below should be enough:                                addVarsToClass($pluginClassInstance, $this->_plugins[$pluginid], array( 'params', 'classinstance' ));
538
                                        $pluginClassInstance->element        =        $this->_plugins[$pluginid]->element;        // needed for _getPrefix for _getReqParam & co
539
                                        $savePreviousPluginId                        =        $this->_loading;
540
                                        $this->_loading                                        =        $pluginid;
541
                                        $ret                                                        =        call_user_func_array( array( &$pluginClassInstance, $method ), $args );
542
                                        $this->_loading                                        =        $savePreviousPluginId;
543
                                        return $ret;
544
                                }
545
                        }
546
                } elseif (function_exists( $method )) {
547
                        if ( $this->_plugins[$pluginid]->published || $ignorePublishedStatus ) {
548
                                $this->_loadParams($pluginid, $extraParams);
549
550
                                $savePreviousPluginId                                =        $this->_loading;
551
                                $this->_loading                                                =        $pluginid;
552
                                $ret                                                                =        call_user_func_array( $method, $args );
553
                                $this->_loading                                                =        $savePreviousPluginId;
554
                                return $ret;
555
                        } 
556
                }
557
                return false;
558
        }
559
560
        /**
561
        * PRIVATE method: sets the text of the last error
562
        * @access private
563
        *
564
        * @param  string   $msg   error message
565
        * @return boolean         true
566
        */
567
        function _setErrorMSG( $msg ) {
568
                $this->errorMSG[]        =        $msg;
569
                return true;
570
        }
571
        /**
572
        * Gets the text of the last error:
573
        * $separator == FALSE:  always returns array
574
        * $separator is string: returns null or string of errors
575
        *
576
        * @param  string|boolean  $separator   FALSE: return array, STRING: Separator between the errors which are imploded from array
577
        * @return string|array                 Text for error message or array of texts of error messages.
578
        */
579
        function getErrorMSG( $separator = "\n" ) {
580
                if ( $separator === false ) {
581
                        return $this->errorMSG;
582
                } else {
583
                        $error                =        null;
584
                        if ( count( $this->errorMSG ) > 0 ) {
585
                                $error        =        implode( $separator, $this->errorMSG );
586
                        }
587
                        return $error;
588
                }
589
        }
590
        /**
591
        * PRIVATE method: sets the error condition and priority (for now 0)
592
        * @param error priority
593
        * @return boolean true
594
        */        
595
        function raiseError($priority) {
596
                $this->_iserror                =        true;
597
                return true;
598
        }
599
        
600
        /**
601
        * Gets the debug text
602
        * @returns string text for debug
603
        */
604
        function getDebugMSG() {
605
                return $this->debugMSG;
606
        }
607
        /**
608
        * PRIVATE method: sets the text of the last error
609
        * @returns void
610
        */
611
        function _setDebugMSG($method,$msg) {
612
                $debugARRAY=array();
613
                $debugARRAY['class']=get_class($this);
614
                $debugARRAY['method']=$method;
615
                $debugARRAY['msg']=$msg;
616
                $this->debugMSG[]=$debugARRAY;
617
                return true;
618
        }
619
620
        /**
621
         * XML LOAD AND ACCESS METHOD:
622
         */
623
624
        /**
625
         * xml file for plugin
626
         *
627
         * @param  string             $actionType
628
         * @param  string             $action
629
         * @param  int                $pluginId
630
         * @return CBSimpleXMLElement
631
         */
632
        function & loadPluginXML( $actionType, $action, $pluginId = null ) {
633
                global $_CB_framework;
634
635
                static $cache                                                =        array();
636
637
                cbimport('cb.xml.simplexml');
638
639
                $row                                                                =&        $this->getPluginObject( $pluginId );
640
                $xmlString                                                        =        null;
641
642
                if ( $row ) {
643
                        // security sanitization to disable use of `/`, `\\` and `:` in $action variable
644
                        $unsecureChars                                        =        array( '/', '\\', ':', ';', '{', '}', '(', ')', "\"", "'", '.', ',', "\0", ' ', "\t", "\n", "\r", "\x0B" );
645
                        $classname                                                =        'CBplug_' . strtolower( substr( str_replace( $unsecureChars, '', $row->element ), 0, 32 ) );
646
                        $action_cleaned                                        =                                strtolower( substr( str_replace( $unsecureChars, '', $action ),                  0, 32 ) );
647
                        
648
                        if ( isset( $cache[$classname][$actionType][$action_cleaned] ) ) {
649
                                return $cache[$classname][$actionType][$action_cleaned];
650
                        }
651
652
                        if ( class_exists( $classname ) ) {
653
                                // class CBplug_pluginname exists:
654
                                if ( ( $_CB_framework->getUi() == 2 ) && is_callable( array( $classname, 'loadAdmin' ) ) ) {
655
                                        // function loadAdmin exists:
656
                                        $array                                        =        array();
657
                                        $this->call( $row->id, 'loadAdmin', $classname, $array, null, true );
658
                                }
659
                                // $xmlString        =        $pluginClass->getXml( 'action', $action_cleaned );
660
                                $array                =        array( $actionType, $action_cleaned );
661
                                $xmlString        =        $this->call( $row->id, 'getXml', $classname, $array, null, true );
662
                                if ( $xmlString ) {
663
                                        $cache[$classname][$actionType][$action_cleaned]        =&        new CBSimpleXMLElement( $xmlString );
664
                                        return $cache[$classname][$actionType][$action_cleaned];
665
                                }
666
                        }
667
668
                        if ( $action_cleaned ) {
669
                                // try action-specific file: xml/edit.actiontype.xml :
670
                                $xmlfile        =        $_CB_framework->getCfg('absolute_path') . '/'. $this->getPluginRelPath( $row ) . '/xml/edit.' . $actionType . '.' . $action_cleaned .'.xml';
671
                                if ( file_exists( $xmlfile ) ) {
672
                                        $cache[$classname][$actionType][$action_cleaned]        =&        new CBSimpleXMLElement( trim( file_get_contents( $xmlfile ) ) );
673
                                        return $cache[$classname][$actionType][$action_cleaned];
674
                                }
675
                        }
676
                        // try specific file for after installations: xml/edit.plugin.xml :
677
                        $xmlfile                =        $_CB_framework->getCfg('absolute_path') . '/'. $this->getPluginRelPath( $row ) . '/xml/edit.plugin.xml';
678
                        if ( file_exists( $xmlfile ) ) {
679
                                $cache[$classname][$actionType][$action_cleaned]                =&        new CBSimpleXMLElement( trim( file_get_contents( $xmlfile ) ) );
680
                                return $cache[$classname][$actionType][$action_cleaned];
681
                        }
682
683
                        // try plugin installation file:
684
                        $xmlfile                =        $_CB_framework->getCfg('absolute_path') . '/'. $this->getPluginRelPath( $row ) . '/' . $row->element . '.xml';
685
                        if ( isset( $cache[$xmlfile] ) ) {
686
                                return $cache[$xmlfile];
687
                        } else {
688
                                if ( file_exists( $xmlfile ) ) {
689
                                        $cache[$xmlfile]                =&        new CBSimpleXMLElement( trim( file_get_contents( $xmlfile ) ) );
690
                                        return $cache[$xmlfile];
691
                                }
692
                        }
693
                        $row->description                                =        '<b><font style="color:red;">Plugin not installed</font></b>';
694
                }
695
                $element                                                        =        null;
696
                return $element;
697
        }
698
699
}        // end class cbPluginHandler
700
701
/**
702
* Event Class for handling the CB event api
703
* @package Community Builder
704
* @author JoomlaJoe
705
*/
706
class cbEventHandler extends cbPluginHandler  {
707
708
        /**
709
        * Constructor
710
        */
711
        function cbEventHandler() {
712
                $this->cbPluginHandler();
713
        }
714
}
715
716
/**
717
* Field Class for handling the CB field api
718
* @package Community Builder
719
* @author Beat
720
*/
721
class cbFieldHandler extends cbPluginHandler  {
722
        /** Plugin of this field
723
         * @var moscomprofilerPlugin */
724
        var $_plugin        =        null;
725
        /** XML of the Plugin of this field
726
         * @var CBSimpleXMLElement */
727
        var $_xml                =        null;
728
        /** XML of this field
729
         * @var CBSimpleXMLElement */
730
        var $_fieldXml        =        null;
731
        /**
732
        * Constructor
733
        */
734
        function cbFieldHandler() {
735
                $this->cbPluginHandler();
736
        }
737
        /**
738
         * Overridable methods:
739
         */
740
        /**
741
         * Initializer:
742
         * Puts the default value of $field into $user (for registration or new user in backend)
743
         *
744
         * @param  moscomprofilerFields  $field
745
         * @param  moscomprofilerUser    $user
746
         * @param  string                $reason      'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
747
         */
748
        function initFieldToDefault( &$field, &$user, $reason ) {
749
                foreach ( $field->getTableColumns() as $col ) {
750
                        if ( $reason == 'search' ) {
751
                                $user->$col                                                        =        null;
752
                        } else {
753
                                $user->$col                                                        =        $field->default;
754
                        }
755
                }
756
        }
757
        /**
758
         * Formatter:
759
         * Returns a field in specified format
760
         *
761
         * @param  moscomprofilerFields  $field
762
         * @param  moscomprofilerUser    $user
763
         * @param  string                $output      'html', 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist', 'htmledit'
764
         * @param  string                $formatting  'tr', 'td', 'div', 'span', 'none',   'table'??
765
         * @param  string                $reason      'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
766
         * @param  int                   $list_compare_types   IF reason == 'search' : 0 : simple 'is' search, 1 : advanced search with modes, 2 : simple 'any' search
767
         * @return mixed                
768
         */
769
        function getFieldRow( &$field, &$user, $output, $formatting, $reason, $list_compare_types ) {
770
                global $ueConfig, $_CB_OneTwoRowsStyleToggle;
771
772
                $results                                                                        =        null;
773
                $oValue                                                                                =        $this->getField( $field, $user, $output, $reason, $list_compare_types );
774
775
                if ( ( ! ( $oValue != null || trim($oValue) != '' ) )
776
                        && ( $output == 'html' )
777
                        && isset( $ueConfig['showEmptyFields'] ) && ( $ueConfig['showEmptyFields'] == 1 )
778
                        && ( $reason != 'search' )
779
                        && ( $field->displaytitle == 1 )
780
                        )
781
                {
782
                        $oValue                                                                        =        cbReplaceVars( $ueConfig['emptyFieldsText'], $user );
783
                }
784
785
                if ( $oValue != null || trim($oValue) != '' ) {
786
                        if ( cbStartOfStringMatch( $output, 'html' ) ) {
787
                                if ( $output == 'htmledit' ) {
788
                                        $htmlDescription                                =        $this->getFieldDescription( $field, $user, 'htmledit', $reason );
789
                                        $labelTitle                                                =        ( trim( strip_tags( $htmlDescription ) ) ? ' title="' . htmlspecialchars( $this->getFieldTitle( $field, $user, 'html', $reason ) ) . ':' . htmlspecialchars( $htmlDescription ) . '"' : '' );
790
                                        // removed in fieldEditToHtml
791
                                } else {
792
                                        $labelTitle                                                =        '';
793
                                }
794
795
                                if ( $field->displaytitle != -1 ) {
796
                                        $label                                                =        '<label for="' . ( $output == 'htmledit' ? htmlspecialchars( $field->name ) : 'cbfv_' . $field->fieldid ) . '"' . $labelTitle . '>';
797
                                        $labelEnd                                        =        '</label>';
798
                                } else {
799
                                        $label                                                =        '';
800
                                        $labelEnd                                        =        '';
801
                                }
802
803
                                switch ( $formatting ) {
804
                                        case 'table':
805
                                                // ?
806
                                                break;
807
                
808
                                        case 'tr':
809
                                                if ( ( $field->name == 'avatar' ) && ( $reason == 'profile' ) ) {
810
                                                        $class                                                =        'cbavatar_tr';                        // ugly temporary fix
811
                                                } else {
812
                                                        $class                                                 =        'sectiontableentry' . $_CB_OneTwoRowsStyleToggle;
813
                                                        $_CB_OneTwoRowsStyleToggle        =        ( $_CB_OneTwoRowsStyleToggle == 1 ? 2 : 1 );
814
                                                }
815
                                                $class                                                .=        ' cbft_' . $field->type;
816
                                                $results                                        .=        "\n\t\t\t\t<tr class=\"" . $class. '" id="cbfr_' . $field->fieldid . '">';
817
                                                $colspan                                        =        ( ( $field->profile == 2 ) ? ' colspan="2"' : '' );
818
                                                if ( ( $field->displaytitle === null ) || ( $field->displaytitle == 1 ) || ( $output == 'htmledit' ) ) {
819
                                                        $translatedTitle                =        $this->getFieldTitle( $field, $user, $output, $reason );
820
                                                        if ( trim( $translatedTitle ) == '' ) {
821
                                                                $colspan                        =        ' colspan="2"';                // CB 1.0-1.1 backwards compatibility
822
                                                        }
823
                                                } else {
824
                                                        $translatedTitle                =        '';
825
                                                }
826
                                                if( trim( $translatedTitle ) != '' ) {
827
                                                        $results                                .=        "\n\t\t\t\t\t<td class=\"titleCell\"" . $colspan .'>'
828
                                                                                                        .        $label
829
                                                                                                        .        $translatedTitle
830
                                                                                                        .        ':'
831
                                                                                                        .        $labelEnd
832
                                                                                                        .        '</td>';
833
                                                        if ( $field->profile == 2 ) {
834
                                                                $results                        .=        "\n\t\t\t\t</tr>"
835
                                                                                                        .        "\n\t\t\t\t<tr class=\"" . $class . '">';
836
                                                        }
837
                                                }
838
                                                $results                                        .=        "\n\t\t\t\t\t<td" . $colspan . ' class="fieldCell" id="cbfv_' . $field->fieldid . '">' . $oValue . '</td>';
839
                                                $results                                        .=        "\n\t\t\t\t</tr>";
840
                                                break;
841
        
842
                                        case 'td':
843
                                                $class                                                =        ' cbft_' . $field->type;
844
                                                $results                                        .=        "\n\t\t\t\t\t" . '<td class="fieldCell' . $class . '" id="cbfv_' . $field->fieldid . '">' . $oValue . '</td>';
845
                                                break;
846
        
847
                                        case 'div':
848
                                                $class                                                 =        'sectiontableentry' . $_CB_OneTwoRowsStyleToggle;
849
                                                $_CB_OneTwoRowsStyleToggle        =        ( $_CB_OneTwoRowsStyleToggle == 1 ? 2 : 1 );
850
                                                $class                                                .=        ' cbft_' . $field->type;
851
                                                $translatedTitle                        =        $this->getFieldTitle( $field, $user, $output, $reason );
852
                                                $results                                        .=        "\n\t\t\t\t"
853
                                                                                                        .        '<div class="' . $class . ' cb_form_line cbclearboth" id="cbfr_' . $field->fieldid . '">';
854
                                                if ( trim( $translatedTitle ) != '' ) {
855
                                                        $results                                .=        $label
856
                                                                                                        .        $translatedTitle
857
                                                                                                        .        ':'
858
                                                                                                        .        $labelEnd
859
                                                                                                        ;
860
                                                }
861
                                                $results                                        .=        '<div class="cb_field"><div id="cbfv_' . $field->fieldid . '">'
862
                                                                                                        .        $oValue
863
                                                                                                        .        '</div>'
864
                                                                                                        //        <div class="cb_result_container"><div id="checkemail__Response">&nbsp;</div></div>        // space for AJAX reply
865
                                                                                                        .        '</div></div>'
866
                                                                                                        ;
867
                                                break;
868
                
869
                                        case 'span':
870
                                                $class                                                =        ' cbft_' . $field->type;
871
                                                $results                                        .=        '<span class="cb_field' . $class . '"><span id="cbfv_' . $field->fieldid . '">'
872
                                                                                                        .        $oValue
873
                                                                                                        .        '</span></span>';
874
                                                break;
875
                
876
                                        case 'ul':
877
                                        case 'ol':
878
                                                break;
879
880
                                        case 'li':
881
                                                $translatedTitle                        =        $this->getFieldTitle( $field, $user, $output, $reason );
882
                                                if ( trim( $translatedTitle ) != '' ) {
883
                                                        $translatedTitle                =        '<span class="cb_title">' . $translatedTitle . ':' . '</span> ';
884
                                                }
885
                                                $class                                                =        ' cbft_' . $field->type;
886
                                                $results                                        .=        '<li class="cb_field' . $class . '">'
887
                                                                                                        .        $translatedTitle
888
                                                                                                        .        '<span id="cbfv_' . $field->fieldid . '">'
889
                                                                                                        .        $oValue
890
                                                                                                        .        '</span></li>';
891
                                                break;
892
893
                                        case 'none':
894
                                                $results                                        =        $oValue;
895
                                                break;
896
                
897
                                        default:
898
                                                $results                                        =        '*' . $oValue . '*';
899
                                                break;
900
                                }
901
                        } else {
902
                                $results                                                        =        $oValue;
903
                        }
904
                }
905
                return $results;
906
        }
907
908
        /**
909
         * Accessor:
910
         * Returns a field in specified format
911
         *
912
         * @param  moscomprofilerFields  $field
913
         * @param  moscomprofilerUser    $user
914
         * @param  string                $output  'html', 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist', 'htmledit'
915
         * @param  string                $reason      'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
916
         * @param  int                   $list_compare_types   IF reason == 'search' : 0 : simple 'is' search, 1 : advanced search with modes, 2 : simple 'any' search
917
         * @return mixed
918
         */
919
        function getField( &$field, &$user, $output, $reason, $list_compare_types ) {
920
                $valuesArray                                                        =        array();
921
                foreach ( $field->getTableColumns() as $col ) {
922
                        $valuesArray[]                                                =        $user->get( $col );
923
                }
924
                $value                                                                        =        implode( ', ', $valuesArray );
925
926
                switch ( $output ) {
927
                        case 'html':
928
                        case 'rss':
929
                                return $this->_formatFieldOutput( $field->name, $value, $output, true );
930
                        case 'htmledit':
931
                                if ( $reason == 'search' ) {
932
                                        return        $this->_fieldSearchModeHtml( $field, $user, $this->_fieldEditToHtml( $field, $user, $reason, 'input', $field->type, $value, '' ), 'text', $list_compare_types );
933
                                } else {
934
                                        return $this->_fieldEditToHtml( $field, $user, $reason, 'input', $field->type, $value, '' );
935
                                }
936
                                break;
937
938
                        default:
939
                                return $this->_formatFieldOutput( $field->name, $value, $output, false );
940
                                break;
941
                }
942
        }
943
        /**
944
         * Labeller for title:
945
         * Returns a field title
946
         *
947
         * @param  moscomprofilerFields  $field
948
         * @param  moscomprofilerUser    $user
949
         * @param  string                $output  'text' or: 'html', 'htmledit', (later 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist')
950
         * @param  string                $reason      'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
951
         * @return string
952
         */
953
        function getFieldTitle( &$field, &$user, $output, $reason ) {
954
                if ( $output === 'text' ) {
955
                        return strip_tags( cbReplaceVars( $field->title, $user ) );
956
                } else {
957
                        return cbReplaceVars( $field->title, $user );
958
                }
959
        }
960
        /**
961
         * Labeller for description:
962
         * Returns a field title
963
         *
964
         * @param  moscomprofilerFields  $field
965
         * @param  moscomprofilerUser    $user
966
         * @param  string                $output  'text' or: 'html', 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist', 'htmledit'
967
         * @param  string                $reason      'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
968
         * @return string
969
         */
970
        function getFieldDescription( &$field, &$user, $output, $reason ) {
971
                if ( $output === 'text' ) {
972
                        return trim( strip_tags( cbReplaceVars( $field->description, $user ) ) );
973
                } elseif ( $output === 'htmledit' ) {
974
                        return trim( cbReplaceVars( $field->description, $user ) );
975
                } else {
976
                        return null;
977
                }
978
        }
979
        /**
980
         * Mutator:
981
         * Prepares field data for saving to database (safe transfer from $postdata to $user)
982
         * Override
983
         *
984
         * @param  moscomprofilerFields  $field
985
         * @param  moscomprofilerUser    $user      RETURNED populated: touch only variables related to saving this field (also when not validating for showing re-edit)
986
         * @param  array                 $postdata  Typically $_POST (but not necessarily), filtering required.
987
         * @param  string                $reason    'edit' for save user edit, 'register' for save registration
988
         */
989
        function prepareFieldDataSave( &$field, &$user, &$postdata, $reason ) {
990
                $this->_prepareFieldMetaSave( $field, $user, $postdata, $reason );
991
                foreach ( $field->getTableColumns() as $col ) {
992
                        $value                                                =        cbGetParam( $postdata, $col );
993
                        if ( ( $value !== null ) && ! is_array( $value ) ) {
994
                                $value                                        =        stripslashes( $value );
995
                                if ( $this->validate( $field, $user, $col, $value, $postdata, $reason ) ) {
996
                                        if ( isset( $user->$col ) && ( (string) $user->$col ) !== (string) $value ) {
997
                                                $this->_logFieldUpdate( $field, $user, $reason, $user->$col, $value );
998
                                        }
999
                                }
1000
                                $user->$col                                =        $value;
1001
                        }
1002
                }
1003
        }
1004
        /**
1005
         * Validator:
1006
         * Validates $value for $field->required and other rules
1007
         * Override
1008
         *
1009
         * @param  moscomprofilerFields  $field
1010
         * @param  moscomprofilerUser    $user        RETURNED populated: touch only variables related to saving this field (also when not validating for showing re-edit)
1011
         * @param  string                $columnName  Column to validate
1012
         * @param  string                $value       (RETURNED:) Value to validate, Returned Modified if needed !
1013
         * @param  array                 $postdata    Typically $_POST (but not necessarily), filtering required.
1014
         * @param  string                $reason      'edit' for save user edit, 'register' for save registration
1015
         * @return boolean                            True if validate, $this->_setErrorMSG if False
1016
         */
1017
        function validate( &$field, &$user, $columnName, &$value, &$postdata, $reason ) {
1018
                global $_CB_framework, $ueConfig;
1019
1020
                if ( ( $_CB_framework->getUi() == 1 ) || ( ( $_CB_framework->getUi() == 2 ) && ( $ueConfig['adminrequiredfields'] == 1 ) ) ) {
1021
1022
                        // Required field:
1023
                        if ( ( $field->required == 1 ) && ( $value == '' ) ) {
1024
                                $this->_setValidationError( $field, $user, $reason, unHtmlspecialchars(_UE_REQUIRED_ERROR) );
1025
                                return false;
1026
                        }
1027
1028
                        $len                                                =        cbIsoUtf_strlen( $value );
1029
1030
                        // Minimum field length:
1031
                        if ( $field->name == 'password' ) {
1032
                                $defaultMin                                =        6;
1033
                        } elseif ( $field->name == 'username' ) {
1034
                                $defaultMin                                =        3;
1035
                        } else {
1036
                                $defaultMin                                =        0;
1037
                        }
1038
                        $fieldMinLength                                =        $field->params->get( 'fieldMinLength', $defaultMin );
1039
1040
                        if ( ( $len > 0 ) && ( $len < $fieldMinLength ) ) {
1041
                                $this->_setValidationError( $field, $user, $reason, sprintf( _UE_VALID_MIN_LENGTH, $this->getFieldTitle( $field, $user, 'text', $reason ), $fieldMinLength, $len ) );
1042
                                return false;
1043
                        }
1044
1045
                        // Maximum field length:
1046
                        $fieldMaxLength                                =        $field->maxlength;
1047
                        if ( $fieldMaxLength && ( $len > $fieldMaxLength ) ) {
1048
                                $this->_setValidationError( $field, $user, $reason, sprintf( _UE_VALID_MAX_LENGTH, $this->getFieldTitle( $field, $user, 'text', $reason ), $fieldMaxLength, $len ) );
1049
                                return false;
1050
                        }
1051
1052
                        // Bad words:
1053
                        if ( ( $reason == 'register' ) && ( in_array( $field->type, array( 'emailaddress', 'primaryemailaddress', 'textarea', 'text', 'webaddress', 'predefined' ) ) ) ) {
1054
                                $defaultForbidden                =        'http:,https:,mailto:,//.[url],<a,</a>,&#';
1055
                        } else {
1056
                                $defaultForbidden                =        '';
1057
                        }
1058
                        $forbiddenContent                        =        $field->params->get( 'fieldValidateForbiddenList_' . $reason, $defaultForbidden );
1059
                        if ( $forbiddenContent != '' ) {
1060
                                $forbiddenContent                =        explode( ',', $forbiddenContent );
1061
                                if ( in_array( '', $forbiddenContent, true ) ) {
1062
                                        // treats case of ',,' or ',,,' to also forbid ',' if in string.
1063
                                        $forbiddenContent[] =        ',';
1064
                                }
1065
                                $replaced                                =        str_replace( $forbiddenContent, '', $value );
1066
                                if ( $replaced != $value ) {
1067
                                        $this->_setValidationError( $field, $user, $reason, _UE_INPUT_VALUE_NOT_ALLOWED );
1068
                                        return false;
1069
                                }
1070
                        }
1071
                }
1072
                return true;
1073
        }
1074
        /**
1075
         * Finder:
1076
         * Prepares field data for saving to database (safe transfer from $postdata to $user)
1077
         * Override
1078
         *
1079
         * @param  moscomprofilerFields  $field
1080
         * @param  moscomprofilerUser    $searchVals  RETURNED populated: touch only variables related to saving this field (also when not validating for showing re-edit)
1081
         * @param  array                 $postdata    Typically $_POST (but not necessarily), filtering required.
1082
         * @param  int                   $list_compare_types   IF reason == 'search' : 0 : simple 'is' search, 1 : advanced search with modes, 2 : simple 'any' search
1083
         * @param  string                $reason      'edit' for save user edit, 'register' for save registration
1084
         * @return array of cbSqlQueryPart
1085
         */
1086
        function bindSearchCriteria( &$field, &$searchVals, &$postdata, $list_compare_types, $reason ) {
1087
                $query                                                        =        array();
1088
                $searchMode                                                =        $this->_bindSearchMode( $field, $searchVals, $postdata, 'text', $list_compare_types );
1089
                if ( $searchMode ) {
1090
                        foreach ( $field->getTableColumns() as $col ) {
1091
                                $value                                        =        cbGetParam( $postdata, $col );
1092
                                if ( ( $value !== null ) && ( $value !== '' ) && ! is_array( $value ) ) {
1093
                                        $value                                =        stripslashes( $value );
1094
                                        $searchVals->$col        =        $value;
1095
                                        // $this->validate( $field, $user, $col, $value, $postdata, $reason );
1096
                                        $sql                                =        new cbSqlQueryPart();
1097
                                        $sql->tag                        =        'column';
1098
                                        $sql->name                        =        $col;
1099
                                        $sql->table                        =        $field->table;
1100
                                        $sql->type                        =        'sql:field';
1101
                                        $sql->operator                =        '=';
1102
                                        $sql->value                        =        $value;
1103
                                        $sql->valuetype                =        'const:string';
1104
                                        $sql->searchmode        =        $searchMode;
1105
                                        $query[]                        =        $sql;
1106
                                }
1107
                        }
1108
                }
1109
                return $query;
1110
        }
1111
        /**
1112
         * Returns a field in specified format
1113
         *
1114
         * @param  string  $name              Sanitized/Safe !!!
1115
         * @param  string  $value
1116
         * @param  string  $output            NO 'htmledit' BUT: 'html', 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist'
1117
         * @param  boolean $htmlspecialchars  TRUE: escape for display, FALSE: not escaped will display raw.
1118
         * @return mixed
1119
         */
1120
        function _formatFieldOutput( $name, $value, $output, $htmlspecialchars = true ) {
1121
1122
                switch ( $output ) {
1123
                        case 'html':
1124
                        case 'rss':
1125
                        case 'htmledit':
1126
                                if ( $htmlspecialchars ) {
1127
                                        return htmlspecialchars( $value );
1128
                                } else {
1129
                                        return $value;
1130
                                }
1131
                                break;
1132
1133
                        case 'xml':
1134
                                if ( $htmlspecialchars ) {
1135
                                        return '<' . htmlspecialchars( $name ) . '>' . htmlspecialchars( htmlspecialchars( $value ) ) . '</' .htmlspecialchars( $name ) . '>';
1136
                                } else {
1137
                                        return '<' . htmlspecialchars( $name ) . '>' . htmlspecialchars( $value ) . '</' . htmlspecialchars( $name ) . '>';
1138
                                }
1139
                                break;
1140
1141
                        case 'json':
1142
                                return "'" . addslashes( $name ) . "' : '" . addslashes( $value ) . "'";
1143
                                break;
1144
1145
                        case 'php':
1146
                                return array( $name => $value );
1147
                                break;
1148
1149
                        case 'fieldslist':
1150
                                return $name;
1151
                                break;
1152
1153
                        case 'csvheader':
1154
                                $value                =        $name;
1155
                                // on purpose fall-through:
1156
                        case 'csv':
1157
                                if ( ! preg_match( '/",\n\r\t/', $value ) ) {
1158
                                        return $value;
1159
                                } else {
1160
                                        return  '"' . str_replace( '"', '""', $value ) . '"';
1161
                                }
1162
                                break;
1163
1164
                        default:
1165
                                trigger_error( '_formatFieldOutput called with ' . htmlspecialchars( $output ), E_USER_WARNING );
1166
                                return $value;
1167
                                break;
1168
                }
1169
        }
1170
        /**
1171
         * Returns a field in specified format
1172
         *
1173
         * @param  moscomprofilerField  $field
1174
         * @param  moscomprofilerUser   $user
1175
         * @param  string               $output  NO 'htmledit' BUT: 'html', 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist', 'htmledit'
1176
         * @return mixed                
1177
         */
1178
        function _formatFieldOutputIntBoolFloat( $name, $value, $output ) {
1179
1180
                switch ( $output ) {
1181
                        case 'html':
1182
                        case 'rss':
1183
                                return $value; 
1184
                                break;
1185
1186
                        case 'htmledit':
1187
                                trigger_error( '_formatFieldOutput called with htmledit', E_USER_WARNING );
1188
                                return null;
1189
                                break;
1190
1191
                        case 'xml':
1192
                                return '<' . $name . '>' . $value . '</' . $name . '>';
1193
                                break;
1194
1195
                        case 'json':
1196
                                return "'" . $name . "' : " . $value;
1197
                                break;
1198
1199
                        case 'php':
1200
                                return array( $name => $value );
1201
                                break;
1202
1203
                        case 'csvheader':
1204
                        case 'fieldslist':
1205
                                return $name;
1206
                                break;
1207
1208
                        case 'csv':
1209
                                return $value;
1210
                        default:
1211
                                trigger_error( '_formatFieldOutput called with ' . htmlspecialchars( $output ), E_USER_WARNING );
1212
                                return $value;
1213
                                break;
1214
                }
1215
        }
1216
        /**
1217
         * Reformats a PHP array into $output format
1218
         *
1219
         * @param  array   $retArray  Named array
1220
         * @param  string  $output  'html', 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist', 'htmledit'
1221
         * @return mixed
1222
         */
1223
        function _arrayToFormat( &$field, $vals, $output, $listType = ', ', $class = '' ) {
1224
                switch ( $output ) {
1225
                        case 'html':
1226
                        case 'rss':
1227
                                foreach ( $vals as $k => $v ) {
1228
                                           $vals[$k]                        =        htmlspecialchars( $v );
1229
                                }
1230
                                switch ( $listType ) {
1231
                                        case 'ul':
1232
                                        case 'ol':
1233
                                                if ( count( $vals ) > 0 ) {
1234
                                                        if ( $class != '' ) {
1235
                                                                $class        =        ' class="' . htmlspecialchars( $class ) . '"';
1236
                                                        }
1237
                                                        return '<' . $listType . $class . '><li>' . implode( '</li><li>', $vals ) . '</li></' . $listType . '>';
1238
                                                } else {
1239
                                                        return null;
1240
                                                }
1241
                                                break;
1242
                                
1243
                                        case ', ':
1244
                                        default:
1245
                                                return implode( $listType, $vals );
1246
                                                break;
1247
                                }
1248
                                break;
1249
1250
                        case 'htmledit':
1251
                                break;
1252
1253
                        case 'xml':
1254
                                foreach ( $vals as $k => $v ) {
1255
                                           $vals[$k]        =        '<value>' . htmlspecialchars( $v ) . '</value>';
1256
                                }
1257
                                return '<' . htmlspecialchars( $field->name ) . '>' . implode( '', $vals ) . '</' . htmlspecialchars( $field->name ) . '>';
1258
                                break;
1259
1260
                        case 'json':
1261
                                foreach ( $vals as $k => $v ) {
1262
                                           $vals[$k]        =        "'" . addslashes( $v ) . "'";
1263
                                }
1264
                                return "'" . addslashes( $field->name ) . "' : { " .  implode( ', ', $vals ) . " }";
1265
                                break;
1266
1267
                        case 'php':
1268
                                return array( $field->name => $vals );
1269
                                break;
1270
1271
                        case 'csv':
1272
                                $valsString                =        implode( ',', $vals );
1273
                                return $this->_formatFieldOutput( $field->name, $valsString, $output, false );
1274
                                break;
1275
1276
                        case 'csvheader':
1277
                        case 'fieldslist':
1278
                        default:
1279
                                break;
1280
                }
1281
                trigger_error( '_arrayToFormat called with non-implemented output type: ' . htmlspecialchars( $output ), E_USER_WARNING );
1282
                return null;
1283
        }
1284
        /**
1285
         * Reformats a PHP array of links into $output format
1286
         *
1287
         * @param  array   $retArray  Named array
1288
         * @param  string  $output  'html', 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist', 'htmledit'
1289
         * @return mixed
1290
         */
1291
        function _linksArrayToFormat( &$retArray, $output ) {
1292
                switch ( $output ) {
1293
                        case 'html':
1294
                        case 'rss':
1295
                                $imploded        =        null;
1296
                                foreach ( $retArray as $res ) {
1297
                                        if ( isset( $res['url' ] ) ) {
1298
                                                $imploded        .=        '<a href="' . cbSef( $res["url"] ) . '" title="' . getLangDefinition( $res["tooltip"] ) . '">' . $res['title'] . '</a> ';
1299
                                        }
1300
                                }
1301
                                return $imploded;
1302
                                break;
1303
1304
                        case 'htmledit':
1305
                                break;
1306
1307
                        case 'xml':
1308
                                break;
1309
1310
                        case 'json':
1311
                                break;
1312
1313
                        case 'php':
1314
                                break;
1315
1316
                        case 'csvheader':
1317
                        case 'fieldslist':
1318
                                break;
1319
1320
                        case 'csv':
1321
                        default:
1322
                                break;
1323
                }
1324
                trigger_error( '_arrayToFormat called with non-implemented output type: ' . htmlspecialchars( $output ), E_USER_WARNING );
1325
                return null;
1326
        }
1327
        /**
1328
         * Returns the activity update corresponding to the logged values
1329
         *
1330
         * @param  moscomprofilerFields       $field
1331
         * @param  moscomprofilerActivity     $activity
1332
         * @param  moscomprofilerUser         $user
1333
         * @param  string  $output            NO 'htmledit' BUT: 'html', 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist'
1334
         * @param  boolean $htmlspecialchars  TRUE: escape for display, FALSE: not escaped will display raw.
1335
         * @return mixed
1336
         */
1337
        function _formatFieldActivityOutput( &$field, &$activity, &$user, $output, $htmlspecialchars = true ) {
1338
                $name                =        $field->name;
1339
/*
1340
                global $_CB_framework, $ueConfig;
1341
                $value                =        '<a href="' . $_CB_framework->userProfileUrl( $user->id ) . '">'
1342
                                        .        getNameFormat( $user->name, $user->username, $ueConfig['name_format'] )
1343
                                        .        '</a>'
1344
                                        .        ' updated his '
1345
*/
1346
                $value                                =        $this->_formatFieldOutput( $field->name, $activity->new_value, $output, $htmlspecialchars );
1347
                switch ( $output ) {
1348
                        case 'html':
1349
                        case 'rss':
1350
                        case 'htmledit':
1351
                                $title                =        $this->getFieldTitle( $field, $user, $output, 'profile' );
1352
                                if ( $htmlspecialchars ) {
1353
                                        return sprintf( '%s %s %s', '<span class="titleCell">' . $title . '</span>', '<span class="cbIs">' . CBTxt::Th('is now') . '</span>', '<span class="fieldCell">' . htmlspecialchars( $value ) . '</span>' );
1354
                                } else {
1355
                                        return sprintf( CBTxt::T('%s is now %s'), $title, $value );                //FIXME : LANGUAGE STRINGS FOR THIS !
1356
                                }
1357
                                break;
1358
1359
                        case 'xml':
1360
                                return '<' . $name . '>' . htmlspecialchars( $value ) . '</' . $name . '>';                // htmlspecialchars handled already by _formatFieldOutput
1361
                                break;
1362
1363
                        case 'json':
1364
                                return "'" . $name . "' : '" . addslashes( $value ) . "'";
1365
                                break;
1366
1367
                        case 'php':
1368
                                return array( $name => $value );
1369
                                break;
1370
1371
                        case 'csvheader':
1372
                        case 'fieldslist':
1373
                                return $name;
1374
                                break;
1375
1376
                        case 'csv':
1377
                                return '"' . addslashes( $value ) . '"';
1378
                                break;
1379
1380
                        default:
1381
                                trigger_error( '_formatFieldActivityOutput called with ' . htmlspecialchars( $output ), E_USER_WARNING );
1382
                                return $value;
1383
                                break;
1384
                }
1385
        }
1386
        /**
1387
         * Private methods for front-end:
1388
         */
1389
        /**
1390
         * converts to HTML
1391
         *
1392
         * @param  moscomprofilerFields  $field
1393
         * @param  moscomprofilerUser    $user
1394
         * @param  string                $reason      'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
1395
         * @param  string                $tag         <tag
1396
         * @param  string                $type        type="$type"
1397
         * @param  string                $value       value="$value"
1398
         * @param  string                $additional  'xxxx="xxx" yy="y"'  WARNING: No classes in here, use $classes
1399
         * @param  string                $allValues   
1400
         * @param  boolean               $displayFieldIcons
1401
         * @param  array                 $classes     CSS classes
1402
         * @return string                            HTML: <tag type="$type" value="$value" xxxx="xxx" yy="y" />
1403
         */
1404
        function _fieldEditToHtml( &$field, &$user, $reason, $tag, $type, $value, $additional, $allValues = null, $displayFieldIcons = true, $classes = null ) {
1405
                $readOnly                                =        $this->_isReadOnly( $field, $user, $reason );
1406
                $oReq                                        =        $this->_isRequired( $field, $user, $reason );
1407
1408
                if ( $readOnly ) { 
1409
                        $additional                        .=        ' disabled="disabled"';
1410
                        $oReq                                =        0;
1411
                }
1412
                if ( $oReq ) {
1413
                        $classes[]                        =        'required';
1414
                        $additional                        .=        ' mosReq="1"'                                                //TBD: replace by class
1415
                                                                .        ' mosLabel="' . htmlspecialchars( $this->getFieldTitle( $field, $user, 'text', $reason ) ) . '"';
1416
                }
1417
                if ( $field->size > 0 ) {
1418
                        $additional                        .=        ' size="' . $field->size . '" ';
1419
                }
1420
                $inputName                                =        $field->name;
1421
                switch ( $type ) {
1422
                        case 'radio':
1423
                                if ( $classes ) {
1424
                                        $additional        .=        ' class="' . implode( ' ', $classes ) . '"';
1425
                                }
1426
                                return moscomprofilerHTML::radioListTable( $allValues, $inputName, $additional, 'value', 'text', $value, $field->cols, $field->rows, $field->size, $oReq )
1427
                                .        $this->_fieldIconsHtml( $field, $user, 'htmledit', $reason, $tag, $type, $value, $additional, $allValues, $displayFieldIcons, $oReq );
1428
                                break;
1429
1430
                        case 'multiselect':
1431
                                $additional                .=        ' multiple="multiple"';
1432
                                if ( $classes ) {
1433
                                        $additional        .=        ' class="' . implode( ' ', $classes ) . '"';
1434
                                }
1435
                                $inputName                .=        '[]';
1436
                                // no break on purpose for fall-through:
1437
                        case 'select':
1438
                                $classes[]                =        'inputbox';
1439
                                $additional                .=        ' class="' . implode( ' ', $classes ) . '"';
1440
                                return moscomprofilerHTML::selectList( $allValues, $inputName, $additional, 'value', 'text', $this->_explodeCBvaluesToObj( $value ), 0 /* $oReq */ )        //TODO: REMOVE TEMP!!!!!!!!
1441
                                .        $this->_fieldIconsHtml( $field, $user, 'htmledit', $reason, $tag, $type, $value, $additional, $allValues, $displayFieldIcons, $oReq );
1442
                                break;
1443
1444
                        case 'multicheckbox':
1445
                                $additional                .=        ' size="' . $field->size . '"';
1446
                                if ( $classes ) {
1447
                                        $additional        .=        ' class="' . implode( ' ', $classes ) . '"';
1448
                                }
1449
                                return moscomprofilerHTML::checkboxListTable( $allValues, $inputName . '[]', $additional, 'value', 'text', $this->_explodeCBvaluesToObj( $value ), $field->cols, $field->rows, $field->size, $oReq )
1450
                                .        $this->_fieldIconsHtml( $field, $user, 'htmledit', $reason, $tag, $type, $value, $additional, $allValues, $displayFieldIcons, $oReq );
1451
                                break;
1452
1453
                        case 'password':
1454
                                $additional                .=        ' autocomplete="off"';
1455
                                // on purpose no break here !
1456
                        case 'text':
1457
                        case 'primaryemailaddress':
1458
                        case 'emailaddress':
1459
                        case 'webaddress':
1460
                        case 'predefined':
1461
                                if ( $field->size == 0 ) {
1462
                                        $additional                        .=        ' size="25"';
1463
                                }
1464
                                if ( $field->maxlength > 0 ) {
1465
                                        $additional        .=        ' maxlength="' . $field->maxlength . '"';        
1466
                                }
1467
                                $classes[]                =        'inputbox';
1468
                                break;
1469
1470
                        case 'textarea':
1471
                                $tag                        =        'textarea';
1472
                                $type                        =        null;
1473
                                if ( $field->cols > 0 ) {
1474
                                        $additional        .=        ' cols="' . $field->cols . '"';        
1475
                                }
1476
                                if ( $field->rows > 0 ) {
1477
                                        $additional        .=        ' rows="' . $field->rows . '"';        
1478
                                }
1479
                                $classes[]                =        'inputbox';
1480
                                break;
1481
1482
                        case 'html':
1483
                                return $value;
1484
                                break;
1485
1486
                        default:
1487
                                break;
1488
                }
1489
                if ( $classes ) {
1490
                        $additional        .=        ' class="' . implode( ' ', $classes ) . '"';
1491
                }
1492
                $htmlDescription                =        $this->getFieldDescription( $field, $user, 'htmledit', $reason );                //TODO : REMOVE ! with the one just below!
1493
                return        '<' . $tag
1494
                                .        ( $type ? ' type="' . $type . '"' : '' )
1495
                                .        ' name="' . $inputName . '" id="' . $inputName . '"'
1496
                                .        ( $tag == 'textarea' ? '' : ' value="' . htmlspecialchars( $value ) . '"' )
1497
                                .        ( $additional ? ' ' . $additional : '' )
1498
                                .        ( trim( strip_tags( $htmlDescription ) ) ? ' title="' . htmlspecialchars( $this->getFieldTitle( $field, $user, 'html', $reason ) ) . ':' . htmlspecialchars( $htmlDescription ) . '"' : '' )                        //TODO : remove !
1499
                                .        ( $tag == 'textarea' ? '>' .  htmlspecialchars( $value ) . '</textarea>' : ' />' )
1500
                                .        $this->_fieldIconsHtml( $field, $user, 'htmledit', $reason, $tag, $type, $value, $additional, $allValues, $displayFieldIcons, $oReq )
1501
                                ;
1502
                }
1503
        /**
1504
         * Displays field icons
1505
         *
1506
         * @param  moscomprofilerFields  $field
1507
         * @param  moscomprofilerUser    $user
1508
         * @param  string                $output
1509
         * @param  string                $reason      'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
1510
         * @param  string                $tag         <tag
1511
         * @param  string                $type        type="$type"
1512
         * @param  string                $value       value="$value"
1513
         * @param  string                $additional  'xxxx="xxx" yy="y"'
1514
         * @param  string                $allValues
1515
         * @param  boolean               $displayFieldIcons
1516
         * @param  boolean               $required
1517
         * @return string                             HTML
1518
         */
1519
        function _fieldIconsHtml( &$field, &$user, $output, $reason, $tag, $type, $value, $additional, $allValues, $displayFieldIcons, $required ) {
1520
                global $_CB_framework, $_PLUGINS;
1521
1522
                $results                                =        $_PLUGINS->trigger( 'onFieldIcons', array( &$this, &$field, &$user, $output, $reason, $tag, $type, $value, $additional, $allValues, $displayFieldIcons, $required ) );
1523
                if ( count( $results ) > 0 ) {
1524
                        return implode( '', $results );
1525
                } else {
1526
                        if ( $displayFieldIcons && ( $reason != 'search' ) ) {
1527
                                return getFieldIcons( $_CB_framework->getUi(), $required, $field->profile, $this->getFieldDescription( $field, $user, $output, $reason ), $this->getFieldTitle( $field, $user, $output, $reason ) );
1528
                        } else {
1529
                                return null;
1530
                        }
1531
                }                
1532
        }
1533
        function _isRequired( &$field, &$user, $reason ) {
1534
                global $_CB_framework, $ueConfig;
1535
1536
                $adminReq                                =        $field->required;
1537
                if (        ( $_CB_framework->getUi() == 2 )
1538
                        &&        ( $ueConfig['adminrequiredfields']==0 )
1539
                        &&        ! in_array( $field->name, array( 'username', 'email', 'name', 'firstname', 'lastname' ) ) )
1540
                {
1541
                        $adminReq                        =        0;
1542
                }
1543
                return $adminReq;
1544
        }
1545
        function _isReadOnly( &$field, &$user, $reason ) {
1546
                global $_CB_framework;
1547
1548
                $readOnly                                =        $field->readonly;
1549
                if ( ( $_CB_framework->getUi() == 2 ) || ( in_array( $reason, array( 'register', 'search' ) ) ) ) {
1550
                        $readOnly                        =        0;
1551
                }
1552
                return $readOnly;
1553
        }
1554
        function _valueDoesntMatter( &$field, $reason, $noneValue = false ) {
1555
                $value                                        =        new stdClass();
1556
                $value->id                                =        'cbf0_' . $field->fieldid;
1557
                $value->value                        =        '';
1558
                $value->text                        =        ( $reason == 'search' ? ( $noneValue ? _UE_NONE : _UE_NO_PREFERENCE ) : _UE_NO_INDICATION );
1559
                return $value;
1560
        }
1561
        function _explodeCBvaluesToObj( $value ) {
1562
                if ( ! is_array( $value ) ) {
1563
                        $value                                =        explode( '|*|', $value );
1564
                }
1565
                $objArr                                        =        array();
1566
                foreach( $value as $k => $kv ) {
1567
                        $objArr[$k]->value        =        $kv;
1568
                        $objArr[$k]->text        =        $kv;
1569
                }
1570
                return $objArr;
1571
        }
1572
        function _explodeCBvalues( $value ) {
1573
                return explode( '|*|', $value );
1574
        }
1575
        function _implodeCBvalues( $value ) {
1576
                return implode( '|*|', $value );
1577
        }
1578
        function _fieldSearchRangeModeHtml( &$field, &$user, $output, $reason, $value, $minHtml, $maxHtml, $list_compare_types ) {
1579
                $html        =        '<div>'
1580
                .        '<span class="cbSearchFromTo cbSearchFrom">'
1581
                .        _UE_SEARCH_FROM
1582
                .        '</span> <span class="cbSearchFromVal">'
1583
                .        $minHtml
1584
                .        '</span>'
1585
                .        '</div>'
1586
                .        '<div>'
1587
                .        '<span class="cbSearchFromTo cbSearchTo">'
1588
                .        _UE_SEARCH_TO
1589
                .        '</span> <span class="cbSearchToVal">'
1590
                .        $maxHtml
1591
                .        '</span>'
1592
                .        $this->_fieldIconsHtml( $field, $user, $output, $reason, null, $field->type, $value, 'input', null, true, false )
1593
                .        '</div>'
1594
                ;
1595
                return $this->_fieldSearchModeHtml( $field, $user, $html, 'isisnot', $list_compare_types );
1596
        }
1597
        /**
1598
         * Notifies plugins to log an update to the field (but to wait for the profile saving events to store that log)
1599
         *
1600
         * @param  moscomprofilerFields  $field
1601
         * @param  moscomprofilerUser    $user
1602
         * @param  string                $reason      'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
1603
         * @param  mixed                 $oldValues
1604
         * @param  mixed                 $newValues
1605
         */
1606
        function _logFieldUpdate( &$field, &$user, $reason, $oldValues, $newValues ) {
1607
                global $_PLUGINS;
1608
                $_PLUGINS->trigger( 'onLogChange', array( 'update', 'user', 'field', &$user, &$this->_plugin, &$field, $oldValues, $newValues, $reason ) );
1609
        }
1610
        /**
1611
         * Outputs search format including $html being html with input fields
1612
         *
1613
         * @param  moscomprofilerFields  $field
1614
         * @param  moscomprofilerUser    $user
1615
         * @param  string                $html
1616
         * @param  string                $type   'text', 'choice', 'isisnot', 'none'
1617
         * @param  int                   $list_compare_types   IF reason == 'search' : 0 : simple 'is' search, 1 : advanced search with modes, 2 : simple 'any' search
1618
         * @param  string                $class  Extra-class (e.g. for jQuery)
1619
         * @return string
1620
         */
1621
        function _fieldSearchModeHtml( &$field, &$user, $html, $type, $list_compare_types, $class = '' ) {
1622
                switch ($list_compare_types ) {
1623
                        case 1:
1624
                                // Advanced: all possibilities:
1625
                                $col                                                =        $field->name . '__srmch';
1626
                                $selected                                        =        $user->get( $col );
1627
                                switch ( $type ) {
1628
                                        case 'text':
1629
                                                $choices                =        array(        'is'                        =>        _UE_MATCH_IS_EXACTLY,
1630
                                                                                                        'phrase'                =>        _UE_MATCH_PHRASE,
1631
                                                                                                        'all'                        =>        _UE_MATCH_ALL,
1632
                                                                                                        'any'                        =>        _UE_MATCH_ANY,
1633
                                                                                                        '-'                                =>        _UE_MATCH_EXCLUSIONS . ':',
1634
                                                                                                        'isnot'                        =>        _UE_MATCH_IS_EXACTLY_NOT,
1635
                                                                                                        'phrasenot'                =>        _UE_MATCH_PHRASE_NOT,
1636
                                                                                                        'allnot'                =>        _UE_MATCH_ALL_NOT,
1637
                                                                                                        'anynot'                =>        _UE_MATCH_ANY_NOT
1638
                                                                                                );
1639
                                                break;
1640
                                        case 'singlechoice':
1641
                                                $choices                =        array(        'is'                        =>        _UE_MATCH_IS,
1642
                                                                                                        // 'is'                        =>        _UE_MATCH_IS_EXACTLY,
1643
                                                                                                        // 'phrase'                =>        _UE_MATCH_PHRASE,
1644
                                                                                                        // 'all'                        =>        _UE_MATCH_ALL,
1645
                                                                                                        'anyis'                        =>        _UE_MATCH_IS_ONE_OF,                        // _UE_MATCH_ANY,
1646
                                                                                                        '-'                                =>        _UE_MATCH_EXCLUSIONS . ':',
1647
                                                                                                        'isnot'                        =>        _UE_MATCH_IS_NOT,
1648
                                                                                                        // 'phrasenot'        =>        _UE_MATCH_PHRASE_NOT,
1649
                                                                                                        // 'allnot'                =>        _UE_MATCH_ALL_NOT,
1650
                                                                                                        'anyisnot'                =>        _UE_MATCH_IS_NOT_ONE_OF                        // _UE_MATCH_ANY_NOT
1651
                                                                                                );
1652
                                                break;
1653
                                        case 'multiplechoice':
1654
                                                $choices                =        array(        'is'                        =>        _UE_MATCH_ARE_EXACTLY,
1655
                                                                                                        // 'phrase'                =>        _UE_MATCH_PHRASE,
1656
                                                                                                        'all'                        =>        _UE_MATCH_INCLUDE_ALL_OF,
1657
                                                                                                        'any'                        =>        _UE_MATCH_INCLUDE_ANY_OF,
1658
                                                                                                        '-'                                =>        _UE_MATCH_EXCLUSIONS . ':',
1659
                                                                                                        'isnot'                        =>        _UE_MATCH_ARE_EXACTLY_NOT,
1660
                                                                                                        // 'phrasenot'        =>        _UE_MATCH_PHRASE_NOT,
1661
                                                                                                        'allnot'                =>        _UE_MATCH_INCLUDE_ALL_OF_NOT,
1662
                                                                                                        'anynot'                =>        _UE_MATCH_INCLUDE_ANY_OF_NOT
1663
                                                                                                );
1664
                                                break;
1665
                                        case 'isisnot':
1666
                                                $choices                =        array(        'is'                        =>        _UE_MATCH_IS,
1667
                                                                                                        '-'                                =>        _UE_MATCH_EXCLUSIONS . ':',
1668
                                                                                                        'isnot'                        =>        _UE_MATCH_IS_NOT
1669
                                                                                                );
1670
                                                break;
1671
                
1672
                                        case 'none':
1673
                                        default:
1674
                                                $choices                =        null;
1675
                                                break;
1676
                                }
1677
                                if ( $choices !== null ) {
1678
                                        $drop                                =        array();
1679
                                        $drop[]                                =        moscomprofilerHTML::makeOption( '', _UE_NO_PREFERENCE );
1680
                                        $group                                =        false;
1681
                                        foreach ( $choices as $k => $v ) {
1682
                                                if ( $k == '-' ) {
1683
                                                        $drop[]                =        moscomprofilerHTML::makeOptGroup( $v );
1684
                                                        $group                =        true;
1685
                                                } else {
1686
                                                        $drop[]                =        moscomprofilerHTML::makeOption( $k, $v );
1687
                                                }
1688
                                        }
1689
                                        if ( $group ) {
1690
                                                $drop[]                        =        moscomprofilerHTML::makeOptGroup( null );
1691
                                        }
1692
                                        $additional                        =        ' class="inputbox"';
1693
                                        $list                                =        moscomprofilerHTML::selectList( $drop, $field->name . '__srmch', $additional, 'value', 'text', $selected, 1 );
1694
                                } else {
1695
                                        $list                                =        null;
1696
                                }
1697
                                $return                                        =        '<div class="cbSearchContainer cbSearchAdvanced">'
1698
                                                                                .        ( $list ?        '<div class="cbSearchKind">' . $list . '</div>'        :        '' )
1699
                                                                                .        '<div class="cbSearchCriteria' . ( $class ? ' ' . $class : '' ) . '">' . $html . '</div>'
1700
                                                                                . '</div>'
1701
                                                                                ;
1702
                                ;
1703
                                break;
1704
                        
1705
                        case 2:                // Simple "contains" and ranges:
1706
                        case 0:
1707
                        default:
1708
                                // Simple: Only 'is' and ranges:
1709
                                $return                                        =        '<div class="cbSearchContainer cbSearchSimple">'
1710
                                                                                .        '<div class="cbSearchCriteria' . ( $class ? ' ' . $class : '' ) . '">' . $html . '</div>'
1711
                                                                                . '</div>'
1712
                                                                                ;
1713
                                break;
1714
                }
1715
                return $return;
1716
        }
1717
        function _bindSearchMode( &$field, &$searchVals, &$postdata, $type, $list_compare_types ) {
1718
                switch ($list_compare_types) {
1719
                        case 1:
1720
                                $fieldNam                                        =        $field->name . '__srmch';
1721
                                $value                                                =        cbGetParam( $postdata, $fieldNam );
1722
                                if ( $value !== null ) {
1723
                                        $searchVals->$fieldNam        =        stripslashes( $value );
1724
                                }
1725
                                break;
1726
                        
1727
                        case 2:
1728
                                if ( cbGetParam( $postdata, $field->name ) != null ) {
1729
                                        switch ( $type ) {
1730
                                                case 'text':
1731
                                                case 'multiplechoice':
1732
                                                        $value                        =        'any';
1733
                                                        break;
1734
                                                case 'singlechoice':
1735
                                                case 'isisnot':
1736
                                                case 'none':
1737
                                                        $value                        =        'is';
1738
                                                        break;
1739
                        
1740
                                                default:
1741
                                                        $value                        =        null;
1742
                                                        break;
1743
                                        }
1744
                                } else {
1745
                                        $value                                        =        null;
1746
                                }
1747
                                break;
1748
1749
                        case 0:
1750
                        default:
1751
                                if ( cbGetParam( $postdata, $field->name ) != null ) {
1752
                                        $value                                        =        'is';
1753
                                } else {
1754
                                        $value                                        =        null;
1755
                                }
1756
                                break;
1757
                }
1758
                return $value;
1759
        }
1760
        function _bindSearchRangeMode( &$field, &$searchVals, &$postdata, $minName, $maxName, $list_compare_types ) {
1761
                switch ($list_compare_types) {
1762
                        case 1:
1763
                                $value                                                =        $this->_bindSearchMode( $field, $searchVals, $postdata, 'isisnot', $list_compare_types );
1764
                                break;
1765
                        
1766
                        case 2:
1767
                        case 0:
1768
                        default:
1769
                                if ( ( cbGetParam( $postdata, $minName ) != null ) || ( cbGetParam( $postdata, $maxName ) != null ) ) {
1770
                                        $value                                        =        'is';
1771
                                } else {
1772
                                        $value                                        =        null;
1773
                                }
1774
                                break;
1775
                }
1776
                return $value;
1777
        }
1778
        /**
1779
         * Prepares field meta-data for saving to database (safe transfer from $postdata to $user)
1780
         * Override but call parent
1781
         *
1782
         * @param  moscomprofilerFields  $field
1783
         * @param  moscomprofilerUser    $user      RETURNED populated: touch only variables related to saving this field (also when not validating for showing re-edit)
1784
         * @param  array                 $postdata  Typically $_POST (but not necessarily), filtering required.
1785
         * @param  string                $reason      'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
1786
         */
1787
        function _prepareFieldMetaSave( &$field, &$user, &$postdata, $reason ) {
1788
        }
1789
1790
        function ajaxCheckField( &$field, &$user, $reason, $validateParams = null ) {
1791
                global $_CB_framework;
1792
1793
                global $_CB_fieldajax_outputed;
1794
1795
1796
                if ( $_CB_fieldajax_outputed !== true ) {
1797
                        $cbSpoofField                        =        cbSpoofField();
1798
                        $cbSpoofString                        =        cbSpoofString( null, 'fieldclass' );
1799
                        $regAntiSpamFieldName        =        cbGetRegAntiSpamFieldName();
1800
                        $regAntiSpamValues                =        cbGetRegAntiSpams();
1801
        
1802
                        $userid                                        =        (int) $user->id;
1803
        
1804
                        $checking                                 =        _UE_CHECKING;                        // . '&start_debug=1',
1805
                        $live_site                                =        $_CB_framework->getCfg( 'live_site' );
1806
                        $regAntiSpZ                                =        $regAntiSpamValues[0];
1807
1808
                        if ( $_CB_framework->getUi() == 2 ) {
1809
                                $ajaxUrl                        =        $live_site . '/administrator/index3.php';
1810
                        } else {
1811
                                $ajaxUrl                        =        $live_site . '/index2.php';
1812
                        }
1813
                        $_CB_framework->outputCbJQuery( <<<EOT
1814
$.fn.cb_field_ajaxCheck = function() {
1815
        if ( ( $(this).val() != '' ) && ( $(this).val() != $(this).data('cblastvalsent') ) ) {
1816
                var inputid = $(this).attr('id');
1817
                if ( ! $('#'+inputid+'__Response').size() ) {
1818
                        var respField = '<div class=\\"cb_result_container\\"><div id=\\"' + inputid + '__Response\\">&nbsp;</div></div>';
1819
                        $(this).parent().each( function() {
1820
                                if (this.tagName.toLowerCase() == 'td') {
1821
                                        $(this).append(respField);
1822
                                } else {
1823
                                        $(this).after(respField);
1824
                                }
1825
                                $(inputid+'__Response').hide();
1826
                        } );
1827
                }
1828
                if (  $('#'+inputid+'__Response').length > 0 ) {
1829
                        $('#'+inputid+'__Response').html('<img alt=\\"\\" src=\\"$live_site/components/com_comprofiler/images/wait.gif\\" /> $checking').fadeIn('fast');
1830
                        var cbInputField = this;
1831
                        var lastVal = $(this).val();
1832
                        $(this).data('cblastvalsent', lastVal );
1833
                        $.ajax( {        type: 'POST',
1834
                                                url:  '$ajaxUrl?option=com_comprofiler&task=fieldclass&reason=$reason&field='+encodeURIComponent(inputid)+'&function=checkvalue&user=$userid&no_html=1&format=raw',
1835
                                                data: 'value=' + encodeURIComponent( lastVal ) + '&$cbSpoofField=' + encodeURIComponent('$cbSpoofString') + '&$regAntiSpamFieldName=' + encodeURIComponent('$regAntiSpZ'),
1836
                                                success: function(response) {
1837
                                                        var respField = $('#'+$(cbInputField).attr('id')+'__Response');
1838
                                                        respField.fadeOut('fast', function() {
1839
                                                                respField.html(response).fadeIn('fast');
1840
                                                        } );
1841
                                                        $(cbInputField).data( 'cblastvalchecked', lastVal );
1842
                                                },
1843
                                                dataType: 'html'
1844
                        });
1845
                }
1846
        }
1847
};
1848
$.fn.cb_field_ajaxClear = function() {
1849
        var respField = $('#'+$(this).attr('id')+'__Response');
1850
        if ( respField.html() != '&nbsp;' ) {
1851
                if ( $(this).val() != $(this).data( 'cblastvalchecked' ) ) {
1852
                        respField.fadeOut('medium' );
1853
                } else {
1854
                        respField.fadeIn('medium' );
1855
                }
1856
        }
1857
};
1858
EOT
1859
                        );
1860
                        $_CB_fieldajax_outputed                =        true;
1861
                }
1862
1863
                $_CB_framework->outputCbJQuery(
1864
                        // change is broken in FF 2.0.13 when a auto-filled value is chosen
1865
                        "$('#" . $field->name . "').data( 'cblastvalsent', $('#" . $field->name . "').val() ).blur( $.fn.cb_field_ajaxCheck ).keyup( $.fn.cb_field_ajaxClear );"
1866
                );
1867
                return null;
1868
        }
1869
1870
        function _jsValidateClass( $validateRules ) {
1871
                if ( count( $validateRules ) > 0 ) {
1872
                        return '{' . implode( ',', $validateRules ) . '}';
1873
                } else {
1874
                        return null;
1875
                }
1876
                
1877
        }
1878
        /**
1879
         * Direct access to field for custom operations, like for Ajax
1880
         *
1881
         * WARNING: direct unchecked access, except if $user is set, then check well for the $reason ...
1882
         *
1883
         * @param  moscomprofilerFields  $field
1884
         * @param  moscomprofilerUser    $user
1885
         * @param  array                 $postdata
1886
         * @param  string                $reason     'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
1887
         * @return string                            Expected output.
1888
         */
1889
        function fieldClass( &$field, &$user, &$postdata, $reason ) {
1890
                global $_CB_framework;
1891
                // simple spoof check security
1892
                if ( ( ! cbSpoofCheck( 'fieldclass', 'POST', 2 ) ) || ( ( $reason == 'register' ) && ( $_CB_framework->getUi() == 1 ) && ! cbRegAntiSpamCheck( 2 ) ) ) {
1893
                        echo '<span class="cb_result_error">' . _UE_SESSION_EXPIRED . "</span>";
1894
                        exit;
1895
                }
1896
1897
                return false;
1898
        }
1899
        /**
1900
         * Private methods: BACKEND ONLY:
1901
         */
1902
        /**
1903
         * Loads XML file (backend use only!)
1904
         *
1905
         * @param moscomprofilerField $field
1906
         * @return boolean  TRUE if success, FALSE if failed
1907
         */
1908
        function _loadXML( &$field ) {
1909
                global $_PLUGINS;
1910
1911
                if ( ! $field->pluginid ) {
1912
                        // this field pluginid is not up-to-date, try to find the plugin by the php registration method as last resort: load all user plugins for that:
1913
                        if ( ! $_PLUGINS->loadPluginGroup( 'user', null, 0 ) ) {
1914
                                return false;
1915
                        }
1916
                        $field->pluginid        =        $_PLUGINS->getUserFieldPluginId( $field->type );
1917
                }
1918
                if ( $this->_xml === null ) {
1919
                        if ( ! $_PLUGINS->loadPluginGroup( null, array( (int) $field->pluginid ), 0 ) ) {
1920
                                return false;
1921
                        }
1922
                        $this->_xml                =&        $_PLUGINS->loadPluginXML( 'editField', $field->type, $field->pluginid );
1923
                        if ( $this->_xml === null ) {
1924
                                return false;
1925
                        }
1926
                }
1927
                return true;
1928
        }
1929
        /**
1930
         * Loads field XML (backend use only!)
1931
         *
1932
         * @param  moscomprofilerField $field
1933
         * @return CBSimpleXMLElement if success, NULL if failed
1934
         */
1935
        function & _loadFieldXML( &$field ) {
1936
                if ( $this->_fieldXml === null ) {
1937
                        if ( $this->_loadXML( $field ) ) {
1938
                                $fieldTypesXML                        =&        $this->_xml->getElementByPath( 'fieldtypes' );
1939
                                if ( $fieldTypesXML ) {
1940
                                        $this->_fieldXml        =&        $fieldTypesXML->getChildByNameAttr( 'field', 'type', $field->type );
1941
                                }
1942
                        }
1943
                }
1944
                return $this->_fieldXml;
1945
        }
1946
        /**
1947
         * Loads parameters editor (backend use only!)
1948
         *
1949
         * @param moscomprofilerField $field
1950
         * @return cbParamsEditorController or null if not existant
1951
         */
1952
        function & _loadParamsEditor( &$field ) {
1953
                global $_PLUGINS;
1954
                if ( $this->_loadXML( $field ) ) {
1955
                        $plugin                 =        $_PLUGINS->getPluginObject( $field->pluginid );
1956
                        $params                        =&        new cbParamsEditorController( $field->params, $this->_xml, $this->_xml, $plugin );
1957
1958
                        $pluginParams        =        new cbParamsBase( $plugin->params );
1959
                        $params->setPluginParams( $pluginParams );
1960
                } else {
1961
                        $params                        =        null;
1962
                }
1963
                return $params;
1964
        }
1965
        /**
1966
         * Methods for CB backend only (do not override):
1967
         */
1968
        /**
1969
         * Draws parameters editor of the field paramaters (backend use only!)
1970
         *
1971
         * @param  moscomprofilerField  $field
1972
         * @param  array                $options
1973
         * @return string  HTML if editor available, or NULL
1974
         */
1975
        function drawParamsEditor( &$field, &$options ) {
1976
                $params                =&        $this->_loadParamsEditor( $field );
1977
                if ( $params ) {
1978
                        $params->setOptions( $options );
1979
                        return $params->draw( 'params', 'fieldtypes', 'field', 'type', $field->type );
1980
                } else {
1981
                        return null;
1982
                }
1983
        }
1984
        /**
1985
         * Converts returned parameters into raw format of parameters (backend use only!)
1986
         *
1987
         * @param  moscomprofilerField  $field
1988
         * @param  array                $post_Params
1989
         * @return string               for the param column of the field
1990
         */
1991
        function getRawParamsRaw( &$field, &$post_Params ) {
1992
                return stripslashes( cbParamsEditorController::getRawParams( $post_Params ) );
1993
        }
1994
        /**
1995
         * Returns full label of the type of the field (backend use only!)
1996
         *
1997
         * @param  moscomprofilerField $field
1998
         * @return boolean  TRUE if success, FALSE if failed
1999
         */
2000
        function getFieldTypeLabel( &$field, $checkNotSys = true ) {
2001
                $fieldXML                =&        $this->_loadFieldXML( $field );
2002
                if ( $fieldXML ) {
2003
                        if ( $checkNotSys && ( $fieldXML->attributes( 'unique' ) == 'true' ) ) {
2004
                                return null;
2005
                        }
2006
                        return $fieldXML->attributes( 'label' );
2007
                }
2008
                return null;
2009
        }
2010
        /**
2011
         * Returns main table name of $field
2012
         *
2013
         * @param  moscomprofilerFields  $field
2014
         * @return string
2015
         */
2016
        function getMainTable( &$field ) {
2017
                global $_CB_database;
2018
2019
                $fieldXML                                                                                =&        $this->_loadFieldXML( $field );
2020
                if ( $fieldXML ) {
2021
                        $db                                                                                        =&        $fieldXML->getElementByPath( 'database' );
2022
                        if ( $db !== false ) {
2023
2024
                                cbimport( 'cb.sql.upgrader' );
2025
                                $sqlUpgrader                                                        =        new CBSQLupgrader( $_CB_database );
2026
2027
                                return $sqlUpgrader->getMainTableName( $db, $field->name, '#__comprofiler' );
2028
                        }
2029
                }
2030
                return '#__comprofiler';
2031
        }
2032
        /**
2033
         * Returns array of main table columns names of $field
2034
         *
2035
         * @param  moscomprofilerFields  $field
2036
         * @return array
2037
         */
2038
        function getMainTableColumns( &$field ) {
2039
                global $_CB_database;
2040
2041
                $fieldXML                                                                                =&        $this->_loadFieldXML( $field );
2042
                if ( $fieldXML ) {
2043
                        $db                                                                                        =&        $fieldXML->getElementByPath( 'database' );
2044
                        if ( $db !== false ) {
2045
2046
                                cbimport( 'cb.sql.upgrader' );
2047
                                $sqlUpgrader                                                        =        new CBSQLupgrader( $_CB_database );
2048
2049
                                $columnsNames                                                        =        $sqlUpgrader->getMainTableColumnsNames( $db, $field->name );
2050
                                if ( $columnsNames !== false ) {
2051
                                        return $columnsNames;
2052
                                }
2053
2054
                        }
2055
                }
2056
                return array( $field->name );
2057
        }
2058
        /**
2059
         * Handles SQL XML for the type of the field (backend use only!)
2060
         *         <database version="1">
2061
         *                <table name="#__comprofiler" class="moscomprofiler">
2062
         *                        <columns>
2063
         *                                <column name="_rate" nametype="namesuffix" type="sql:decimal(16,8)" unsigned="true" null="true" default="NULL" auto_increment="100" />
2064
         *
2065
         * @param  moscomprofilerFields $field
2066
         * @param  boolean|string       $change   FALSE: only check, TRUE: change database to match description (deleting non-matching columns if $strictlyColumns == true), 'drop': uninstalls columns/tables
2067
         * @param  boolean              $dryRun   FALSE (default): tables are changed, TRUE: Dryrunning
2068
         * @return array of array of array
2069
         */
2070
        function adaptSQL( &$field, $change = true, $dryrun = false ) {
2071
                global $_CB_database;
2072
2073
                cbimport( 'cb.sql.upgrader' );
2074
                $sqlUpgrader                                                                        =        new CBSQLupgrader( $_CB_database );
2075
2076
                $sqlUpgrader->setDryRun( $dryrun );
2077
                return $this->checkFixSQL( $sqlUpgrader, $field, $change );
2078
        }
2079
        /**
2080
         * Check or fix field according to XML description if exsitant (or old method otherwise)
2081
         *
2082
         * @param  CBSQLupgrader         $sqlUpgrader
2083
         * @param  moscomprofilerFields  $field
2084
         * @param  boolean               $change
2085
         * @return unknown
2086
         */
2087
        function checkFixSQL( &$sqlUpgrader, &$field, $change = true ) {
2088
                $fieldXML                                                                                =&        $this->_loadFieldXML( $field );
2089
                if ( $fieldXML ) {
2090
                        $db                                                                                        =&        $fieldXML->getElementByPath( 'database' );
2091
                        if ( $db !== false ) {
2092
                                // <database><table><columns>.... structure:
2093
                                $success                                                                =        $sqlUpgrader->checkXmlDatabaseDescription( $db, $field->name, $change, null );
2094
                        } else {
2095
                                $data                                                                        =&        $fieldXML->getElementByPath( 'data' );
2096
                                if ( $data !== false ) {
2097
                                        // <data ....> structure:
2098
                                        $xmlText                                                        =        '<?xml version="1.0" encoding="UTF-8"?>
2099
<database version="1">
2100
    <table name="' . $field->table . '" maintable="true" strict="false" drop="never" shared="true">
2101
        <columns>
2102
        </columns>
2103
    </table>
2104
</database>';
2105
                                        $dbXml                                                                =&        new CBSimpleXMLElement( $xmlText );
2106
                                        $columns                                                        =&        $dbXml->getElementByPath( 'table/columns' );
2107
                                        $columns->addChildWithAttr( 'column', '', null, $data->attributes() );
2108
                                        $success                                                        =        $sqlUpgrader->checkXmlDatabaseDescription( $dbXml, $field->name, $change, null );
2109
                                } else {
2110
                                        $success                                                        =        true;
2111
                                }
2112
                        }
2113
                } else {
2114
                        // no XML file or no <fieldtype> in xml, must be an old plugin or one which is uninstalled or missing files:
2115
                        cbimport('cb.xml.simplexml');
2116
                        $cols                                                                                =        $field->getTableColumns();
2117
                        if ( count( $cols ) == 0 ) {
2118
                                // the comprofiler_files database is upgraded, but this (status) field does not require comprofiler entries:
2119
                                $success                                                                =        true;
2120
                        } else {
2121
                                // database has been upgraded, take a guess and take first column name as name of the comprofiler table:
2122
                                // or database has not been upgraded: take name:
2123
                                $colNamePrefix                                                        =        $cols[0];
2124
2125
                                $xmlText                                                                =        '<?xml version="1.0" encoding="UTF-8"?>
2126
<database version="1">
2127
    <table name="#__comprofiler" class="moscomprofiler" maintable="true" strict="false" drop="never" shared="true">
2128
        <columns>
2129
            <column name="" nametype="namesuffix" type="sql:varchar(255)" null="true" default="NULL" />
2130
        </columns>
2131
    </table>
2132
</database>';
2133
                                $dbXml                                                                        =&        new CBSimpleXMLElement( $xmlText );
2134
                                $success                                                                =        $sqlUpgrader->checkXmlDatabaseDescription( $dbXml, $colNamePrefix, $change, null );
2135
                        }
2136
                }
2137
                if ( ! $success ) {
2138
                        $field->_error                                                                .=        $sqlUpgrader->getErrors();
2139
                }
2140
/*
2141
var_dump( $success );
2142
echo "<br>\nERRORS: " . $sqlUpgrader->getErrors( "<br /><br />\n\n", "<br />\n" );
2143
echo "<br>\nLOGS: " . $sqlUpgrader->getLogs( "<br /><br />\n\n", "<br />\n" );
2144
//exit;
2145
*/
2146
2147
                return $success;
2148
        }
2149
        /**
2150
         * Sets an error message $errorText for $field of $user
2151
         *
2152
         * @param  moscomprofilerFields  $field
2153
         * @param  moscomprofilerUser    $user
2154
         * @param  string                $reason      'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
2155
         * @param  string                $errorText
2156
         */
2157
        function _setValidationError( &$field, &$user, $reason, $errorText ) {
2158
                $this->_setErrorMSG( $this->getFieldTitle( $field, $user, 'text', $reason ) . ' : ' .  $errorText );
2159
        }
2160
        /**
2161
        * PRIVATE method: sets the text of the last error
2162
        * @access private
2163
        *
2164
        * @param  string   $msg   error message
2165
        * @return boolean         true
2166
        */
2167
        function _setErrorMSG( $msg ) {
2168
                global $_PLUGINS;
2169
2170
                $_PLUGINS->errorMSG[]        =        $msg;
2171
                return true;
2172
        }
2173
}
2174
// cbimport( 'cb.xml.simplexml' );
2175
class cbSqlQueryPart /* extends CBSimpleXMLElement */ {
2176
        var $tag;
2177
        var $name;
2178
        var $table;
2179
        var $type;
2180
        var $operator;
2181
        var $value;
2182
        var $valuetype;
2183
        var $searchmode;
2184
        var $_children                        =        array();
2185
2186
        function addChildren( $children ) {
2187
                $this->_children        =        array_merge( $this->_children, $children );
2188
        }
2189
        function reduceSqlFormula( &$tableReferences, &$joinsSQL, $wildcards = null ) {
2190
                static $replaceWildcards                        =        false;
2191
                static $joinedTableKey                                =        'a';
2192
2193
                if ( $wildcards !== null ) {
2194
                        $replaceWildcards                                =        $wildcards;
2195
                }
2196
                $condition                                                        =        null;
2197
2198
                $subFormulas                                                =        array();
2199
2200
                switch ( $this->name() ) {
2201
                        case 'data':
2202
                                $table                                                =        $this->attributes( 'table' );
2203
                                if ( isset( $tableReferences[$table] ) ) {
2204
                                        $prevJoinKey                        =        $tableReferences[$table];
2205
                                } else {
2206
                                        $prevJoinKey                        =        null;
2207
                                }
2208
                                $joinKey                                        =        'j' . $joinedTableKey;
2209
                                $tableReferences[$table]        =        $joinKey;
2210
                                $joinedTableKey                                =        chr( ord( $joinedTableKey ) + 1 );
2211
                                break;
2212
2213
                        default:
2214
                                break;
2215
                }
2216
2217
                // Recurse:
2218
                foreach ( $this->children() as $child ) {
2219
                        $subFormulas[]                                        =        $child->reduceSqlFormula( $tableReferences, $joinsSQL );
2220
                }
2221
2222
                switch ( $this->name() ) {
2223
                        case 'data':
2224
                                global $_CB_database;
2225
                                if ( count( $subFormulas ) > 0 ) {
2226
                                        $condition                                =        '(' . implode( ') ' . $this->attributes( 'operator' ) . ' (', $subFormulas ) . ')';
2227
                                } else {
2228
                                        $condition                                =        $joinKey . '.' . $this->attributes( 'key' ) . ' = ' . $this->attributes( 'value' );
2229
                                }
2230
2231
                                $joinsSQL[]                                        =        'LEFT JOIN ' . $_CB_database->NameQuote( $table ) . ' AS ' . $joinKey . ' ON ' . $condition;
2232
                                $condition                                        =        $joinKey . '.' . $this->attributes( 'name' );
2233
                                if ( $prevJoinKey ) {
2234
                                        $tableReferences[$table]        =        $prevJoinKey;
2235
                                } else {
2236
                                        unset( $tableReferences[$table] );
2237
                                }
2238
                                break;
2239
2240
                        case 'joinkeys':
2241
                                if ( count( $subFormulas ) > 0 ) {
2242
                                        $condition                                =        '(' . implode( ') ' . $this->attributes( 'operator' ) . ' (', $subFormulas ) . ')';
2243
                                }
2244
                                break;
2245
2246
                        case 'column':
2247
                        case 'where':
2248
                                switch ( $this->attributes( 'type' ) ) {
2249
                                        case 'sql:operator':
2250
                                                if ( count( $subFormulas ) > 0 ) {
2251
                                                        $condition                =        '(' . implode( ') ' . $this->attributes( 'operator' ) . ' (', $subFormulas ) . ')';
2252
                                                }
2253
                                                break;
2254
                                        
2255
                                        case 'sql:function':
2256
                                                if ( count( $subFormulas ) > 0 ) {
2257
                                                        $condition                =        $this->attributes( 'operator' ) . '( ' . implode( ', ', $subFormulas ) . ' )';
2258
                                                }
2259
                                                break;
2260
        
2261
                                        case 'sql:field':
2262
                                                if ( isset( $tableReferences[$this->attributes( 'table' )] ) ) {
2263
                                                        $operator                =        $this->attributes( 'operator' );
2264
                                                        $value                        =        $this->attributes( 'value' );
2265
                                                        $valuetype                =        $this->attributes( 'valuetype' );
2266
                                                        $searchmode                =        $this->attributes( 'searchmode' );
2267
                
2268
                                                        if ( in_array( $operator, array( '=', '<>', '!=' ) ) && ( $valuetype == 'const:string' ) ) {
2269
                                                                switch ( $searchmode ) {
2270
                                                                        case 'all':
2271
                                                                        case 'any':
2272
                                                                        case 'anyis':
2273
                                                                        case 'phrase':
2274
                                                                        case 'allnot':
2275
                                                                        case 'anynot':
2276
                                                                        case 'anyisnot':
2277
                                                                        case 'phrasenot':
2278
                                                                                $precise                                =        in_array( $searchmode, array( 'anyis', 'anyisnot' ) );
2279
                                                                                if ( $replaceWildcards && ! $precise ) {
2280
                                                                                        $this->_replaceWildCards( $operator, $value );                // changes $operator and $value !
2281
                                                                                }
2282
                                                                                if ( is_array( $value ) ) {
2283
                                                                                        $eachValues                        =        $value;
2284
                                                                                } else {
2285
                                                                                        if ( cbStartOfStringMatch( $searchmode, 'phrase' ) ) {
2286
                                                                                                $eachValues                =        array( $value );
2287
                                                                                        } else {
2288
                                                                                                $eachValues                =        preg_split( '/\W+/', $value );
2289
                                                                                        }
2290
                                                                                }
2291
                                                                                $conditions                                =        array();
2292
                                                                                foreach ( $eachValues as $v ) {
2293
                                                                                        if ( $v != '' ) {
2294
                                                                                                if ( ! ( $precise || in_array( $operator, array( 'LIKE', 'NOT LIKE' ) ) ) ) {
2295
                                                                                                        $operator        =        $this->_operatorToLike( $operator );
2296
                                                                                                }
2297
                                                                                                $conditions[]        =        $this->_buildop( $operator, ( $precise ? $v : $this->_prepostfixPercent( $v ) ), $valuetype, $tableReferences );
2298
                                                                                        }
2299
                                                                                }
2300
                                                                                if ( count( $conditions ) > 1 ) {
2301
                                                                                        $op                                        =        ( in_array( $searchmode, array( 'all', 'allnot' ) ) ? ') AND (' : ') OR (' );
2302
                                                                                        $condition                        =        '(' . implode( $op, $conditions ) . ')';
2303
                                                                                } elseif ( count( $conditions ) == 1 ) {
2304
                                                                                        $condition                        =        implode( '', $conditions );
2305
                                                                                } else {
2306
                                                                                        $condition                        =        null;
2307
                                                                                }
2308
                                                                                if ( in_array( $searchmode, array( 'allnot', 'anynot', 'anyisnot', 'phrasenot' ) ) && $condition ) {
2309
                                                                                        $condition                        =        'NOT(' . $condition . ')';
2310
                                                                                }
2311
                                                                                break;
2312
                
2313
                                                                        case 'isnot':
2314
                                                                                $operator                                =        ( $operator == '=' ? '<>' : '=' );
2315
                                                                                $condition                                =        $this->_buildop( $operator, $value, $valuetype, $tableReferences );
2316
                                                                                break;
2317
                
2318
                                                                        case 'is':
2319
                                                                        default:
2320
                                                                                $condition                                =        $this->_buildop( $operator, $value, $valuetype, $tableReferences );
2321
                                                                                break;
2322
                
2323
                                                                }
2324
                                                        } else {
2325
                                                                $condition                                                =        $this->_buildop( $operator, $value, $valuetype, $tableReferences );
2326
                                                        }
2327
                                                }
2328
                                                break;
2329
                                        default:
2330
                                                break;
2331
                                }
2332
                                break;
2333
                        default:
2334
                                break;
2335
                }
2336
                return $condition;
2337
        }
2338
        function _replaceWildCards( &$operator, &$value ) {
2339
                $changes                                =        false;
2340
                if ( is_array( $value ) ) {
2341
                        foreach ( array_keys( $value ) as $k ) {
2342
                                $changes                =        $this->_replaceWildCards( $operator, $value[$k] ) || $changes;
2343
                        }
2344
                } else {
2345
                        $escSearch                                =        str_replace( '|*|', '|`|', $value );
2346
                        if ( strpos( $escSearch, '*' ) !== false ) {
2347
                                $escSearch                        =        cbEscapeSQLsearch( $escSearch );
2348
                                $escSearch                        =        str_replace( '*', '%', $escSearch );
2349
                                $value                                =        str_replace( '|`|', '|*|', $escSearch );
2350
                                $operator                        =        $this->_operatorToLike( $operator );
2351
                                $changes                        =        true;
2352
                        }
2353
                }
2354
                return $changes;
2355
        }
2356
        function _prepostfixPercent( $sqlSearchEscaped ) {
2357
                if ( $sqlSearchEscaped[0] != '%' ) {
2358
                        $sqlSearchEscaped        =        '%' . $sqlSearchEscaped;
2359
                }
2360
                if ( $sqlSearchEscaped[strlen($sqlSearchEscaped) - 1] != '%' ) {
2361
                        $sqlSearchEscaped        .=        '%';
2362
                }
2363
                return $sqlSearchEscaped;
2364
        }
2365
        function _operatorToLike( $operator ) {
2366
                switch ( $operator ) {
2367
                        case '<>':
2368
                        case '!=':
2369
                                $operator        =        'NOT LIKE';
2370
                                break;
2371
2372
                        case '=':
2373
                        default:
2374
                                $operator        =        'LIKE';
2375
                                break;
2376
                }
2377
                return $operator;                
2378
        }
2379
        function _buildop( $operator, $value, $valuetype, &$tableReferences ) {
2380
                global $_CB_database;
2381
2382
                return        $tableReferences[$this->attributes( 'table' )] . '.' . $_CB_database->NameQuote( $this->attributes( 'name' ) )
2383
                                .        ' ' . $operator . ' '
2384
                                .        $this->_sqlCleanQuote( $value, $valuetype )
2385
                                ;
2386
        }
2387
        /**
2388
         * Cleans and makes a value SQL safe depending on the type that is enforced.
2389
         * @access private
2390
         *
2391
         * @param  mixed   $fieldValue
2392
         * @param  string  $type
2393
         * @return string
2394
         */
2395
        function _sqlCleanQuote( $fieldValue, $type ) {
2396
                global $_CB_database;
2397
2398
                $typeArray                =        explode( ':', $type, 3 );
2399
                if ( count( $typeArray ) < 2 ) {
2400
                        $typeArray        =        array( 'const' , $type );
2401
                }
2402
2403
                switch ( $typeArray[1] ) {
2404
                        case 'int':
2405
                                $value                =        (int) $fieldValue;
2406
                                break;
2407
                        case 'float':
2408
                                $value                =        (float) $fieldValue;
2409
                                break;
2410
                        case 'formula':
2411
                                $value                =        $fieldValue;
2412
                                break;
2413
                        case 'field':                                                // this is temporarly handled here
2414
                                $value                =        $_CB_database->NameQuote( $fieldValue );
2415
                                break;
2416
                        case 'datetime':
2417
                                if ( preg_match( '/[0-9]{4}-[01][0-9]-[0-3][0-9] [0-2][0-9](:[0-5][0-9]){2}/', $fieldValue ) ) {
2418
                                        $value        =        $_CB_database->Quote( $fieldValue );
2419
                                } else {
2420
                                        $value        =        "''";
2421
                                }
2422
                                break;
2423
                        case 'date':
2424
                                if ( preg_match( '/[0-9]{4}-[01][0-9]-[0-3][0-9]/', $fieldValue ) ) {
2425
                                        $value        =        $_CB_database->Quote( $fieldValue );
2426
                                } else {
2427
                                        $value        =        "''";
2428
                                }
2429
                                break;
2430
                        case 'string':
2431
                                $value                =        $_CB_database->Quote( $fieldValue );
2432
                                break;
2433
                        case 'null':
2434
                                if ( $fieldValue != 'NULL' ) {
2435
                                        trigger_error( sprintf( 'cbSqlQueryPart::_sqlCleanQuote: ERROR: field type sql:null has not NULL value' ) );
2436
                                }
2437
                                $value                =        'NULL';
2438
                                break;
2439
2440
                        default:
2441
                                trigger_error( 'cbSqlQueryPart::_sqlQuoteValueType: ERROR_UNKNOWN_TYPE: ' . htmlspecialchars( $type ), E_USER_NOTICE );
2442
                                $value                =        $_CB_database->Quote( $fieldValue );        // false;
2443
                                break;
2444
                }
2445
                return (string) $value;
2446
        }
2447
2448
        function name() {
2449
                return $this->tag;
2450
        }
2451
        function attributes( $name = null ) {
2452
                if ( isset( $this->$name ) ) {
2453
                        return $this->$name;
2454
                } else {
2455
                        return null;
2456
                }
2457
        }
2458
        function children( ) {
2459
                return $this->_children;
2460
        }
2461
}
2462
/**
2463
* Field Class for handling the CB field api
2464
* @package Community Builder
2465
* @author Beat
2466
*/
2467
class cbFieldParamsHandler {
2468
        /** Plugin id
2469
         * @var int */
2470
        var $_pluginid        =        null;
2471
        /** field object
2472
         * @var moscomprofilerField */
2473
        var $_field                =        null;
2474
        /** Plugin of this field
2475
         * @var moscomprofilerPlugin */
2476
        var $_plugin        =        null;
2477
        /** XML of the Plugin of this field
2478
         * @var CBSimpleXMLElement */
2479
        var $_xml                =        null;
2480
        /** XML element for the params for this field
2481
         * @var CBSimpleXMLElement */
2482
        var $_fieldXml                =        null;
2483
        /** params are specific to one particular field type
2484
         * @var boolean */
2485
        var $_specific        =        false;
2486
        /**
2487
        * Constructor
2488
        *
2489
        * @param  int                  $pluginid   id of plugin with params for other fields
2490
        * @param  moscomprofilerField  $field
2491
        */
2492
        function cbFieldParamsHandler( $pluginid, &$field ) {
2493
                $this->_pluginid        =        $pluginid;
2494
                $this->_field                =&        $field;
2495
        }
2496
        /**
2497
         * Private methods:
2498
         */
2499
        /**
2500
         * Loads XML file (backend use only!)
2501
         *
2502
         * @return boolean  TRUE if success, FALSE if failed
2503
         */
2504
        function _loadXML( ) {
2505
                global $_PLUGINS;
2506
2507
                if ( $this->_xml === null ) {
2508
                        if ( ! $_PLUGINS->loadPluginGroup( null, array( (int) $this->_pluginid ), 0 ) ) {
2509
                                return false;
2510
                        }
2511
                        $this->_xml        =&        $_PLUGINS->loadPluginXML( 'editField', 'cbfields_params', $this->_pluginid );
2512
                        if ( $this->_xml === null ) {
2513
                                return false;
2514
                        }
2515
                }
2516
                return true;
2517
        }
2518
        /**
2519
         * Loads fields-params XML (backend use only!)
2520
         * also sets $this->_fieldXML and $this->_specific
2521
         *
2522
         * @return boolean              TRUE if success, FALSE if not existant
2523
         */
2524
        function _loadFieldParamsXML( ) {
2525
                if ( $this->_fieldXml === null ) {
2526
                        if ( $this->_loadXML() ) {
2527
                                $fieldsParamsXML                                =&        $this->_xml->getElementByPath( 'fieldsparams' );
2528
                                if ( $fieldsParamsXML ) {
2529
                                        $fieldTypeSpecific                        =&        $fieldsParamsXML->getChildByNameAttr( 'field', 'type', $this->_field->type );
2530
                                        if ( $fieldTypeSpecific ) {
2531
                                                // <fieldsparams><field type="date"><params><param ....
2532
                                                $this->_fieldXml                =&        $fieldTypeSpecific;
2533
                                                $this->_specific                =        true;
2534
                                        } else {
2535
                                                // <fieldsparams><field type="other_types"><params><param ....
2536
                                                $nonSpecific                        =&        $fieldsParamsXML->getChildByNameAttr( 'field', 'type', 'other_types' );
2537
                                                if ( $nonSpecific ) {
2538
                                                        $this->_fieldXml        =&        $nonSpecific;
2539
                                                        $this->_specific        =        false;
2540
                                                }
2541
                                        }
2542
                                }
2543
                        }
2544
                }
2545
                return ( $this->_fieldXml !== null );
2546
        }
2547
        /**
2548
         * Loads parameters editor (backend use only!)
2549
         *
2550
         * @return cbParamsEditorController or null if not existant
2551
         */
2552
        function & _loadParamsEditor() {
2553
                global $_PLUGINS;
2554
                if ( $this->_loadFieldParamsXML() ) {
2555
                        $plugin                 =        $_PLUGINS->getPluginObject( $this->_pluginid );
2556
                        $params                        =&        new cbParamsEditorController( $this->_field->params, $this->_xml, $this->_xml, $plugin );
2557
2558
                        $pluginParams        =        new cbParamsBase( $plugin->params );
2559
                        $params->setPluginParams( $pluginParams );
2560
                } else {
2561
                        $params                        =        null;
2562
                }
2563
                return $params;
2564
        }
2565
        /**
2566
         * Methods for CB backend only (do not override):
2567
         */
2568
        /**
2569
         * Draws parameters editor of the field paramaters (backend use only!)
2570
         *
2571
         * @param  array                $options
2572
         * @return string  HTML if editor available, or NULL
2573
         */
2574
        function drawParamsEditor( &$options ) {
2575
                $params                =&        $this->_loadParamsEditor();
2576
                if ( $params ) {
2577
                        $params->setOptions( $options );
2578
                        if ( $this->_specific ) {
2579
                                return $params->draw( 'params', 'fieldsparams', 'field', 'type', $this->_field->type );
2580
                        } else {
2581
                                return $params->draw( 'params', 'fieldsparams', 'field', 'type', 'other_types' );
2582
                        }
2583
                } else {
2584
                        return null;
2585
                }
2586
        }
2587
        /**
2588
         * Converts returned parameters into raw format of parameters without escaping
2589
         *
2590
         * @param  array                $post_Params
2591
         * @return string               for the param column of the field
2592
         */
2593
        function getRawParamsRaw( &$post_Params ) {
2594
                return stripslashes( cbParamsEditorController::getRawParams( $post_Params ) );
2595
        }
2596
        /**
2597
         * Returns full label of the type of the field (backend use only!)
2598
         *
2599
         * @param  moscomprofilerField $field
2600
         * @return boolean  TRUE if success, FALSE if failed
2601
         */
2602
        function getFieldsParamsLabel() {
2603
                global $_PLUGINS;
2604
                $plugin                                 =        $_PLUGINS->getPluginObject( $this->_pluginid );
2605
                if ( $this->_fieldXml ) {
2606
                        return $plugin->name . ': ' . $this->_fieldXml->attributes( 'label' );
2607
                }
2608
                return $plugin->name . ': ' . "specific field-parameters";
2609
        }
2610
2611
}        // class cbFieldParamsHandler
2612
class cbTabParamsHandler extends cbFieldParamsHandler {
2613
        /**
2614
         * Draws parameters editor of the tab paramaters (backend use only!)
2615
         *
2616
         * @param  array                $options
2617
         * @return string  HTML if editor available, or NULL
2618
         */
2619
        function drawParamsEditor( &$options ) {
2620
                $params                =&        $this->_loadParamsEditor();
2621
                if ( $params ) {
2622
                        $params->setOptions( $options );
2623
                        if ( $this->_specific ) {
2624
                                return $params->draw( 'params', 'tabsparams', 'tab', 'type', $this->_field->pluginclass );
2625
                        } else {
2626
                                return $params->draw( 'params', 'tabsparams', 'tab', 'type', 'other_types' );
2627
                        }
2628
                } else {
2629
                        return null;
2630
                }
2631
        }
2632
        /**
2633
         * Loads XML file (backend use only!)
2634
         *
2635
         * @return boolean  TRUE if success, FALSE if failed
2636
         */
2637
        function _loadXML( ) {
2638
                global $_PLUGINS;
2639
2640
                if ( $this->_xml === null ) {
2641
                        if ( ! $_PLUGINS->loadPluginGroup( null, array( (int) $this->_pluginid ), 0 ) ) {
2642
                                return false;
2643
                        }
2644
                        $this->_xml        =&        $_PLUGINS->loadPluginXML( 'editTab', '