1: <?php
2: /**
3: * Extended User Profile
4: *
5: * You may not change or alter any portion of this comment or credits
6: * of supporting developers from this source code or any supporting source code
7: * which is considered copyrighted (c) material of the original comment or credit authors.
8: * This program is distributed in the hope that it will be useful,
9: * but WITHOUT ANY WARRANTY; without even the implied warranty of
10: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11: *
12: * @copyright (c) 2000-2016 XOOPS Project (www.xoops.org)
13: * @license GNU GPL 2 (https://www.gnu.org/licenses/gpl-2.0.html)
14: * @package profile
15: * @since 2.3.0
16: * @author Jan Pedersen
17: * @author Taiwen Jiang <phppp@users.sourceforge.net>
18: */
19:
20: // defined('XOOPS_ROOT_PATH') || exit("XOOPS root path not defined");
21:
22: /**
23: * @package kernel
24: * @copyright (c) 2000-2016 XOOPS Project (www.xoops.org)
25: */
26: class ProfileProfile extends XoopsObject
27: {
28: public $profile_id;
29: public $handler;
30:
31: /**
32: * @param $fields
33: */
34: public function __construct($fields)
35: {
36: $this->initVar('profile_id', XOBJ_DTYPE_INT, null, true);
37: $this->init($fields);
38: }
39:
40: /**
41: * Initiate variables
42: * @param array $fields field information array of {@link XoopsProfileField} objects
43: */
44: public function init($fields)
45: {
46: if (!empty($fields) && \is_array($fields)) {
47: foreach (array_keys($fields) as $key) {
48: $this->initVar($key, $fields[$key]->getVar('field_valuetype'), $fields[$key]->getVar('field_default', 'n'), $fields[$key]->getVar('field_required'), $fields[$key]->getVar('field_maxlength'));
49: }
50: }
51: }
52: }
53:
54: /**
55: * @package kernel
56: * @copyright (c) 2000-2016 XOOPS Project (www.xoops.org)
57: */
58: class ProfileProfileHandler extends XoopsPersistableObjectHandler
59: {
60: /**
61: * holds reference to {@link profileFieldHandler} object
62: */
63: public $_fHandler;
64:
65: /**
66: * Array of {@link XoopsProfileField} objects
67: * @var array
68: */
69: public $_fields = array();
70:
71: /**
72: * @param null|XoopsDatabase $db
73: */
74: public function __construct(XoopsDatabase $db)
75: {
76: parent::__construct($db, 'profile_profile', 'profileprofile', 'profile_id');
77: $this->_fHandler = xoops_getModuleHandler('field', 'profile');
78: }
79:
80: /**
81: * create a new {@link ProfileProfile}
82: *
83: * @param bool $isNew Flag the new objects as "new"?
84: *
85: * @return object {@link ProfileProfile}
86: */
87: public function create($isNew = true)
88: {
89: $obj = new $this->className($this->loadFields());
90: $obj->handler = $this;
91: if ($isNew === true) {
92: $obj->setNew();
93: }
94:
95: return $obj;
96: }
97:
98: /**
99: * Get a ProfileProfile object for a user id.
100: *
101: * We will create an empty profile if none exists. This behavior allows user objects
102: * created outside of profile to be edited correctly in the profile module.
103: *
104: * @param integer|null $uid
105: * @param string[]|null $fields array of field names to fetch, null for all
106: *
107: * @return object {@link ProfileProfile}
108: *
109: * @internal This was get($uid, $createOnFailure = true). No callers found using the extra parameter.
110: * @internal Modified to match parent signature.
111: */
112: public function get($uid = null, $fields = null)
113: {
114: $obj = parent::get($uid, $fields);
115: if (!is_object($obj)) {
116: $obj = $this->create();
117: }
118:
119: return $obj;
120: }
121:
122: /**
123: * Create new {@link ProfileField} object
124: *
125: * @param bool $isNew
126: *
127: * @return ProfileField
128: */
129: public function createField($isNew = true)
130: {
131: $return = $this->_fHandler->create($isNew);
132:
133: return $return;
134: }
135:
136: /**
137: * Load field information
138: *
139: * @return array
140: */
141: public function loadFields()
142: {
143: if (count($this->_fields) == 0) {
144: $this->_fields = $this->_fHandler->loadFields();
145: }
146:
147: return $this->_fields;
148: }
149:
150: /**
151: * Fetch fields
152: *
153: * @param CriteriaElement $criteria {@link CriteriaElement} object
154: * @param bool $id_as_key return array with field IDs as key?
155: * @param bool $as_object return array of objects?
156: *
157: * @return array
158: **/
159: public function getFields(CriteriaElement $criteria, $id_as_key = true, $as_object = true)
160: {
161: return $this->_fHandler->getObjects($criteria, $id_as_key, $as_object);
162: }
163:
164: /**
165: * Insert a field in the database
166: *
167: * @param ProfileField $field
168: * @param bool $force
169: *
170: * @return bool
171: */
172: public function insertField(ProfileField $field, $force = false)
173: {
174: return $this->_fHandler->insert($field, $force);
175: }
176:
177: /**
178: * Delete a field from the database
179: *
180: * @param ProfileField $field
181: * @param bool $force
182: *
183: * @return bool
184: */
185: public function deleteField(ProfileField $field, $force = false)
186: {
187: return $this->_fHandler->delete($field, $force);
188: }
189:
190: /**
191: * Save a new field in the database
192: *
193: * @param array $vars array of variables, taken from $module->loadInfo('profile')['field']
194: * @param int $weight
195: *
196: * @internal param int $categoryid ID of the category to add it to
197: * @internal param int $type valuetype of the field
198: * @internal param int $moduleid ID of the module, this field belongs to
199: * @return string
200: */
201: public function saveField($vars, $weight = 0)
202: {
203: $field = $this->createField();
204: $field->setVar('field_name', $vars['name']);
205: $field->setVar('field_valuetype', $vars['valuetype']);
206: $field->setVar('field_type', $vars['type']);
207: $field->setVar('field_weight', $weight);
208: if (isset($vars['title'])) {
209: $field->setVar('field_title', $vars['title']);
210: }
211: if (isset($vars['description'])) {
212: $field->setVar('field_description', $vars['description']);
213: }
214: if (isset($vars['required'])) {
215: $field->setVar('field_required', $vars['required']); //0 = no, 1 = yes
216: }
217: if (isset($vars['maxlength'])) {
218: $field->setVar('field_maxlength', $vars['maxlength']);
219: }
220: if (isset($vars['default'])) {
221: $field->setVar('field_default', $vars['default']);
222: }
223: if (isset($vars['notnull'])) {
224: $field->setVar('field_notnull', $vars['notnull']);
225: }
226: if (isset($vars['show'])) {
227: $field->setVar('field_show', $vars['show']);
228: }
229: if (isset($vars['edit'])) {
230: $field->setVar('field_edit', $vars['edit']);
231: }
232: if (isset($vars['config'])) {
233: $field->setVar('field_config', $vars['config']);
234: }
235: if (isset($vars['options'])) {
236: $field->setVar('field_options', $vars['options']);
237: } else {
238: $field->setVar('field_options', array());
239: }
240: if ($this->insertField($field)) {
241: $msg = '&nbsp;&nbsp;Field <strong>' . $vars['name'] . '</strong> added to the database';
242: } else {
243: $msg = '&nbsp;&nbsp;<span class="red">ERROR: Could not insert field <strong>' . $vars['name'] . '</strong> into the database. ' . implode(' ', $field->getErrors()) . $this->db->error() . '</span>';
244: }
245: unset($field);
246:
247: return $msg;
248: }
249:
250: /**
251: * insert a new object in the database
252: *
253: * @param XoopsObject|ProfileProfile $obj reference to the object
254: * @param bool $force whether to force the query execution despite security settings
255: *
256: * @return bool FALSE if failed, TRUE if already present and unchanged or successful
257: */
258: public function insert(XoopsObject $obj, $force = false)
259: {
260: if (!($obj instanceof $this->className)) {
261: return false;
262: }
263: $uservars = $this->getUserVars();
264: foreach ($uservars as $var) {
265: unset($obj->vars[$var]);
266: }
267: if (count($obj->vars) == 0) {
268: return true;
269: }
270:
271: return parent::insert($obj, $force);
272: }
273:
274: /**
275: * Get array of standard variable names (user table)
276: *
277: * @return array
278: */
279: public function getUserVars()
280: {
281: return $this->_fHandler->getUserVars();
282: }
283:
284: /**
285: * Search profiles and users
286: *
287: * @param CriteriaElement $criteria CriteriaElement
288: * @param array $searchvars Fields to be fetched
289: * @param array $groups for Usergroups is selected (only admin!)
290: *
291: * @return array
292: */
293: public function search(CriteriaElement $criteria, $searchvars = array(), $groups = null)
294: {
295: $uservars = $this->getUserVars();
296:
297: $searchvars_user = array_intersect($searchvars, $uservars);
298: $searchvars_profile = array_diff($searchvars, $uservars);
299: $sv = array('u.uid, u.uname, u.email, u.user_viewemail');
300: if (!empty($searchvars_user)) {
301: $sv[0] .= ',u.' . implode(', u.', $searchvars_user);
302: }
303: if (!empty($searchvars_profile)) {
304: $sv[] = 'p.' . implode(', p.', $searchvars_profile);
305: }
306:
307: $sql_select = 'SELECT ' . (empty($searchvars) ? 'u.*, p.*' : implode(', ', $sv));
308: $sql_from = ' FROM ' . $this->db->prefix('users') . ' AS u LEFT JOIN ' . $this->table . ' AS p ON u.uid=p.profile_id' . (empty($groups) ? '' : ' LEFT JOIN ' . $this->db->prefix('groups_users_link') . ' AS g ON u.uid=g.uid');
309: $sql_clause = ' WHERE 1=1';
310: $sql_order = '';
311:
312: $limit = $start = 0;
313: if (isset($criteria) && is_subclass_of($criteria, 'CriteriaElement')) {
314: $sql_clause .= ' AND ' . $criteria->render();
315: if ($criteria->getSort() !== '') {
316: $sql_order = ' ORDER BY ' . $criteria->getSort() . ' ' . $criteria->getOrder();
317: }
318: $limit = $criteria->getLimit();
319: $start = $criteria->getStart();
320: }
321:
322: if (!empty($groups)) {
323: $sql_clause .= ' AND g.groupid IN (' . implode(', ', $groups) . ')';
324: }
325:
326: $sql_users = $sql_select . $sql_from . $sql_clause . $sql_order;
327: $result = $this->db->query($sql_users, $limit, $start);
328: if (!$this->db->isResultSet($result)) {
329: return array(array(), array(), 0);
330: }
331:
332: $user_handler = xoops_getHandler('user');
333: $uservars = $this->getUserVars();
334: $users = array();
335: $profiles = array();
336: /** @var array $myrow */
337: while (false !== ($myrow = $this->db->fetchArray($result))) {
338: $profile = $this->create(false);
339: $user = $user_handler->create(false);
340:
341: foreach ($myrow as $name => $value) {
342: if (in_array($name, $uservars)) {
343: $user->assignVar($name, $value);
344: } else {
345: $profile->assignVar($name, $value);
346: }
347: }
348: $profiles[$myrow['uid']] = $profile;
349: $users[$myrow['uid']] = $user;
350: }
351:
352: $count = count($users);
353: if ((!empty($limit) && $count >= $limit) || !empty($start)) {
354: $sql_count = 'SELECT COUNT(*)' . $sql_from . $sql_clause;
355: $result = $this->db->query($sql_count);
356: if (!$this->db->isResultSet($result)) {
357: throw new \RuntimeException(
358: \sprintf(_DB_QUERY_ERROR, $sql_count) . $this->db->error(), E_USER_ERROR
359: );
360: }
361: list($count) = $this->db->fetchRow($result);
362: }
363:
364: return array($users, $profiles, (int)$count);
365: }
366: }
367: