/** * Filling the gaps in marker groups * * @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops) */ public function step2() { $order = 2; foreach (\IPS\Db::i()->select('*', 'membermap_markers_groups') as $group) { $group = \IPS\membermap\Markers\Groups::constructFromData($group); \IPS\Lang::saveCustom('membermap', "membermap_marker_group_{$group->id}", trim($group->name)); \IPS\Lang::saveCustom('membermap', "membermap_marker_group_{$group->id}_JS", trim($group->name), 1); $group->name_seo = \IPS\Http\Url::seoTitle(trim($group->name)); if ($group->type == 'custom') { $group->position = $order; $group->moderate = 1; $order++; } try { $latestMarker = \IPS\Db::i()->select('*', 'membermap_markers', array('marker_open=? and marker_parent_id=?', 1, $group->id), 'marker_updated DESC, marker_added DESC', array(0, 1))->first(); $group->last_marker_id = $latestMarker['marker_id']; $group->last_marker_date = $latestMarker['marker_added']; } catch (\UnderflowException $e) { $group->last_marker_id = 0; $group->last_marker_date = 0; } $group->save(); /* Reset permissions */ $perms = $group->permissions(); \IPS\Db::i()->update('core_permission_index', array('perm_view' => '*', 'perm_2' => '*', 'perm_3' => \IPS\Settings::i()->admin_group, 'perm_4' => \IPS\Settings::i()->admin_group), array('perm_id=?', $perms['perm_id'])); } return TRUE; }
/** * Get node classes * * @return array */ public function getNodeClasses() { return array('IPS\\membermap\\Markers\\Groups' => function ($current, $group) { $rows = array(); foreach (\IPS\membermap\Markers\Groups::roots(NULL) as $groups) { \IPS\membermap\Markers\Groups::populatePermissionMatrix($rows, $groups, $group, $current); } return $rows; }); }
/** * ... * * @return void */ protected function manage() { if (isset(\IPS\Request::i()->id)) { try { $this->_group(\IPS\membermap\Markers\Groups::loadAndCheckPerms(\IPS\Request::i()->id, 'view')); } catch (\OutOfRangeException $e) { \IPS\Output::i()->error('node_error', '2MM2/1', 404, ''); } } else { $this->_index(); } }
/** * Submit Event * * @return void */ protected function manage() { $group = NULL; if (isset(\IPS\Request::i()->group)) { try { $group = \IPS\membermap\Markers\Groups::loadAndCheckPerms(\IPS\Request::i()->group); \IPS\Output::i()->breadcrumb[] = array(\IPS\Http\Url::internal('app=membermap&module=groups&controller=groups&id=' . $group->_id, 'front', 'markers_group', $group->name_seo), $group->_title); } catch (\OutOfRangeException $e) { } } $form = \IPS\membermap\Markers\Markers::create($group); if (\IPS\membermap\Markers\Markers::moderateNewItems(\IPS\Member::loggedIn())) { $form = \IPS\Theme::i()->getTemplate('forms', 'core')->modQueueMessage(\IPS\Member::loggedIn()->warnings(5, NULL, 'mq'), \IPS\Member::loggedIn()->mod_posts) . $form; } /* Display */ \IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('membermap_submit_a_marker'); \IPS\Output::i()->sidebar['enabled'] = FALSE; \IPS\Output::i()->breadcrumb[] = array(NULL, \IPS\Member::loggedIn()->language()->addToStack('membermap_submit_a_marker')); \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('submit')->submitPage($form->customTemplate(array(call_user_func_array(array(\IPS\Theme::i(), 'getTemplate'), array('submit', 'membermap')), 'submitForm'))); }
/** * Member account has been updated * * @param $member \IPS\Member Member updating profile * @param $changes array The changes * @return void */ public function onProfileUpdate($member, $changes) { /* An endless loop is formed when \Item::createItem() is saving \Member, which then fire this membersync, which then calls \Item::createItem, and so on, and so on */ static $wereDoneHere = false; if ($wereDoneHere) { return; } $wereDoneHere = true; if (isset($changes['name'])) { $existingMarker = \IPS\membermap\Map::i()->getMarkerByMember($member->member_id, FALSE, FALSE); if ($existingMarker instanceof \IPS\membermap\Markers\Markers) { $existingMarker->name = $member->name; $existingMarker->updated = time(); $existingMarker->save(); } } if (count($changes) and \IPS\Settings::i()->membermap_monitorLocationField and !$member->members_bitoptions['bw_is_spammer']) { if (\IPS\Settings::i()->membermap_monitorLocationField_groupPerm === '*' or \IPS\Member::loggedIn()->inGroup(explode(',', \IPS\Settings::i()->membermap_monitorLocationField_groupPerm))) { if (isset($changes['field_' . \IPS\Settings::i()->membermap_profileLocationField]) and !empty($changes['field_' . \IPS\Settings::i()->membermap_profileLocationField])) { try { $lat = $lng = $location = NULL; $fieldValue = $changes['field_' . \IPS\Settings::i()->membermap_profileLocationField]; /* If it's an array, it might be from an address field, which already have the lat/lng data */ if (is_array(json_decode($fieldValue, TRUE))) { $addressData = json_decode($fieldValue, TRUE); if (is_float($addressData['lat']) and is_float($addressData['long'])) { $lat = floatval($addressData['lat']); $lng = floatval($addressData['long']); } $addressData['addressLines'][] = $addressData['city']; if (count($addressData['addressLines'])) { $location = implode(', ', $addressData['addressLines']); } } else { /* Remove HTML, newlines, tab, etc, etc */ $fieldValue = preg_replace("/[\\x00-\\x20]|\\xc2|\\xa0+/", ' ', strip_tags($fieldValue)); $fieldValue = trim(preg_replace("/\\s\\s+/", ' ', $fieldValue)); /* To my understanding we're not allowed to use \IPS\Geolocation, as that uses Google API, and we're not showing the info on a Google Map. */ $nominatim = \IPS\membermap\Map::i()->getLatLng($fieldValue); if (is_array($nominatim) and count($nominatim)) { $lat = $nominatim['lat']; $lng = $nominatim['lng']; $location = $nominatim['location']; } } if ($lat and $lng) { $existingMarker = \IPS\membermap\Map::i()->getMarkerByMember($member->member_id, FALSE); if ($existingMarker instanceof \IPS\membermap\Markers\Markers) { $marker = $existingMarker; $marker->updated = time(); } else { $groupId = \IPS\membermap\Map::i()->getMemberGroupId(); $marker = \IPS\membermap\Markers\Markers::createItem($member, \IPS\Request::i()->ipAddress(), new \IPS\DateTime(), \IPS\membermap\Markers\Groups::load($groupId)); } $marker->name = $member->name; $marker->lat = $lat; $marker->lon = $lng; $marker->location = $location ?: $fieldValue; /* Save and add to search index */ $marker->save(); \IPS\Content\Search\Index::i()->index($marker); } } catch (\Exception $e) { /* Something went wrong. Such as the input field being an editor */ \IPS\Log::log($e, 'membermap'); return false; } } } } }
/** * Loads add/update location form * * @return void */ protected function add() { if (!\IPS\Member::loggedIn()->member_id) { \IPS\Output::i()->error('no_permission', '2MM3/1', 403, ''); } /* Get the members location, if it exists */ $existing = \IPS\membermap\Map::i()->getMarkerByMember(\IPS\Member::loggedIn()->member_id, FALSE); $groupId = \IPS\membermap\Map::i()->getMemberGroupId(); /* Check permissions */ if ($existing) { if (!$existing->canEdit()) { \IPS\Output::i()->error('membermap_error_cantEdit', '2MM3/2', 403, ''); } } else { if (!\IPS\membermap\Markers\Groups::load($groupId)->can('add')) { \IPS\Output::i()->error('membermap_error_cantAdd', '2MM3/3', 403, ''); } } /* HTML5 GeoLocation form */ $geoLocForm = new \IPS\Helpers\Form('membermap_form_geoLocation', NULL, NULL, array('id' => 'membermap_form_geoLocation')); $geoLocForm->class = 'ipsForm_vertical ipsType_center'; $geoLocForm->addHeader('membermap_current_location'); $geoLocForm->addHtml('<li class="ipsType_center"><i class="fa fa-fw fa-4x fa-location-arrow"></i></li>'); $geoLocForm->addHtml('<li class="ipsType_center">' . \IPS\Member::loggedIn()->language()->addToStack('membermap_geolocation_desc') . '</li>'); $geoLocForm->addButton('membermap_current_location', 'button', NULL, 'ipsButton ipsButton_primary', array('id' => 'membermap_currentLocation')); $form = new \IPS\Helpers\Form('membermap_form_location', NULL, NULL, array('id' => 'membermap_form_location')); $form->class = 'ipsForm_vertical ipsType_center'; $form->addHeader('membermap_form_location'); $form->add(new \IPS\Helpers\Form\Text('membermap_location', '', FALSE, array('placeholder' => \IPS\Member::loggedIn()->language()->addToStack('membermap_form_placeholder')), NULL, NULL, NULL, 'membermap_location')); $form->addButton('save', 'submit', NULL, 'ipsPos_center ipsButton ipsButton_primary', array('id' => 'membermap_locationSubmit')); $form->hiddenValues['lat'] = \IPS\Request::i()->lat; $form->hiddenValues['lng'] = \IPS\Request::i()->lng; if ($values = $form->values()) { try { /* Create marker */ if ($existing instanceof \IPS\membermap\Markers\Markers) { $marker = $existing; $marker->updated = time(); } else { $marker = \IPS\membermap\Markers\Markers::createItem(\IPS\Member::loggedIn(), \IPS\Request::i()->ipAddress(), new \IPS\DateTime(), \IPS\membermap\Markers\Groups::load($groupId)); $marker->member_id = \IPS\Member::loggedIn()->member_id; } if (isset($values['membermap_location']) and !empty($values['membermap_location'])) { $marker->location = $values['membermap_location']; } $marker->name = \IPS\Member::loggedIn()->name; $marker->lat = $values['lat']; $marker->lon = $values['lng']; $marker->save(); /* Add to search index */ \IPS\Content\Search\Index::i()->index($marker); /* Content approval is requred, redirect the member to the marker page, where this is made clear */ if ($marker->hidden()) { \IPS\Output::i()->redirect($marker->url()); } else { \IPS\Output::i()->redirect(\IPS\Http\Url::internal('app=membermap&module=membermap&controller=showmap&dropBrowserCache=1&goHome=1', 'front', 'membermap')); } return; } catch (\Exception $e) { $form->error = \IPS\Member::loggedIn()->language()->addToStack('membermap_' . $e->getMessage()); \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('map')->addLocation($geoLocForm, $form); return; } } \IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack(!$existing ? 'membermap_button_addLocation' : 'membermap_button_editLocation'); \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('map')->addLocation($geoLocForm, $form); }
public function import() { $id = isset(\IPS\Request::i()->id) ? intval(\IPS\Request::i()->id) : 0; /* Build form */ $form = new \IPS\Helpers\Form(NULL, 'import'); if (isset(\IPS\Request::i()->id)) { $group = \IPS\membermap\Markers\Groups::load(intval(\IPS\Request::i()->id)); if ($group->type == 'member') { \IPS\Output::i()->error('generic_error', '1MM4/1', 403, ''); } } $form->add(new \IPS\Helpers\Form\Upload('import_upload', NULL, TRUE, array('allowedFileTypes' => array('kml'), 'temporary' => TRUE))); $form->add(new \IPS\Helpers\Form\YesNo('import_creategroups', FALSE, FALSE, array('togglesOff' => array('import_group')))); $form->add(new \IPS\Helpers\Form\Node('import_group', $id ?: 0, FALSE, array('class' => '\\IPS\\membermap\\Markers\\Groups', 'permissionCheck' => 'add', 'subnodes' => false, 'where' => array('group_type != ?', 'member')), NULL, NULL, NULL, 'import_group')); if ($values = $form->values()) { try { $xml = \IPS\Xml\SimpleXML::loadFile($values['import_upload']); } catch (\InvalidArgumentException $e) { $form->error = \IPS\Member::loggedIn()->language()->addToStack('xml_upload_invalid'); \IPS\Output::i()->output = $form; return; } /* No group selected, and don't create groups?! */ if ($values['import_creategroups'] == FALSE and !$values['import_group']) { $form->error = \IPS\Member::loggedIn()->language()->addToStack('membermap_error_no_id_no_create'); \IPS\Output::i()->output = $form; return; } $markers = array(); $groupOrder = NULL; $imported = 0; foreach ($xml->Document->Folder as $folder) { if (!isset($folder->Placemark)) { continue; } $folderName = (string) $folder->name; foreach ($folder->Placemark as $placemark) { if (!isset($placemark->Point->coordinates)) { continue; } list($lon, $lat, $elev) = explode(',', $placemark->Point->coordinates); $markers[] = array('marker_name' => (string) $placemark->name, 'marker_name_seo' => \IPS\Http\Url::seoTitle((string) $placemark->name), 'marker_description' => (string) $placemark->description, 'marker_lat' => $lat, 'marker_lon' => $lon, 'marker_member_id' => \IPS\Member::loggedIn()->member_id, 'marker_added' => time(), 'marker_open' => 1, 'marker_parent_id' => isset($values['import_group']) ? $values['import_group']->id : NULL); } /* Create a new group per "folder" */ if ($values['import_creategroups'] == TRUE and count($markers) > 0) { if ($groupOrder === NULL) { $groupOrder = \IPS\Db::i()->select(array("MAX( `group_position` ) as position"), 'membermap_markers_groups')->first(); } $groupOrder = $groupOrder + 1; $group = new \IPS\membermap\Markers\Groups(); $group->name = $folderName; $group->name_seo = \IPS\Http\Url::seoTitle($folderName); $group->type = 'custom'; $group->pin_colour = '#FFFFFF'; $group->pin_bg_colour = 'red'; $group->pin_icon = 'fa-globe'; $group->position = $groupOrder; $group->save(); \IPS\Lang::saveCustom('membermap', "membermap_marker_group_{$group->id}", trim($folderName)); \IPS\Lang::saveCustom('membermap', "membermap_marker_group_{$group->id}_JS", trim($folderName), 1); // Add group id to all elements of the array array_walk($markers, function (&$v, $k) use($group) { $v['marker_parent_id'] = $group->id; }); // Insert \IPS\Db::i()->insert('membermap_markers', $markers); $group->setLastComment(); $group->save(); // Set default permissions $perms = $group->permissions(); \IPS\Db::i()->update('core_permission_index', array('perm_view' => '*', 'perm_2' => '*', 'perm_3' => \IPS\Settings::i()->admin_group, 'perm_4' => \IPS\Settings::i()->admin_group), array('perm_id=?', $perms['perm_id'])); // Reset $imported += count($markers); $markers = array(); } } /* If we still got markers here, it's all pushed to one group, probably */ if (is_array($markers) and count($markers) > 0) { \IPS\Db::i()->insert('membermap_markers', $markers); $group = $values['import_group']; $group->setLastComment(); $group->save(); $imported += count($markers); } \IPS\membermap\Map::i()->invalidateJsonCache(); $message = \IPS\Member::loggedIn()->language()->addToStack('membermap_import_thumbup', FALSE, array('sprintf' => array($imported))); \IPS\Output::i()->redirect(\IPS\Http\Url::internal("app=membermap&module=membermap&controller=markers"), $message); } /* Display */ \IPS\Output::i()->output = $form; }
/** * Execute * * If ran successfully, should return anything worth logging. Only log something * worth mentioning (don't log "task ran successfully"). Return NULL (actual NULL, not '' or 0) to not log (which will be most cases). * If an error occurs which means the task could not finish running, throw an \IPS\Task\Exception - do not log an error as a normal log. * Tasks should execute within the time of a normal HTTP request. * * @return mixed Message to log or NULL * @throws \IPS\Task\Exception */ public function execute() { if (!\IPS\Settings::i()->membermap_syncLocationField or !\IPS\Settings::i()->membermap_monitorLocationField or !\IPS\Settings::i()->membermap_profileLocationField) { $this->enabled = FALSE; $this->save(); return; } $fieldKey = \IPS\Settings::i()->membermap_profileLocationField; $limit = 100; $counter = 0; $memberMarkerGroupId = \IPS\membermap\Map::i()->getMemberGroupId(); try { $where = array(); $where[] = array("( pf.field_{$fieldKey} IS NOT NULL OR pf.field_{$fieldKey} != '' )"); $where[] = array("mm.marker_id IS NULL"); $where[] = array("m.membermap_location_synced = 0"); $where[] = array('( ! ' . \IPS\Db::i()->bitwiseWhere(\IPS\Member::$bitOptions['members_bitoptions'], 'bw_is_spammer') . ' )'); if (\IPS\Settings::i()->membermap_monitorLocationField_groupPerm !== '*') { $where[] = \IPS\Db::i()->in('m.member_group_id', explode(',', \IPS\Settings::i()->membermap_monitorLocationField_groupPerm)); } $members = \IPS\Db::i()->select('*', array('core_members', 'm'), $where, 'm.last_activity DESC', array(0, $limit))->join(array('core_pfields_content', 'pf'), 'pf.member_id=m.member_id')->join(array('membermap_markers', 'mm'), 'mm.marker_member_id=m.member_id AND mm.marker_parent_id=' . $memberMarkerGroupId); foreach ($members as $member) { $lat = $lng = $location = NULL; $_member = \IPS\Member::constructFromData($member); /* Need to set this to prevent us from looping over the same members with invalid locations over and over again */ $_member->membermap_location_synced = 1; $_member->save(); $_location = trim($member['field_' . $fieldKey]); if (empty($_location)) { continue; } /* If it's an array, it might be from an address field, which already have the lat/lng data */ if (is_array(json_decode($_location, TRUE))) { $addressData = json_decode($_location, TRUE); if (is_float($addressData['lat']) and is_float($addressData['long'])) { $lat = floatval($addressData['lat']); $lng = floatval($addressData['long']); } $addressData['addressLines'][] = $addressData['city']; if (count($addressData['addressLines'])) { $location = implode(', ', $addressData['addressLines']); } } else { /* Remove HTML, newlines, tab, etc, etc */ $_location = preg_replace("/[\\x00-\\x20]|\\xc2|\\xa0+/", ' ', strip_tags($_location)); $_location = trim(preg_replace("/\\s\\s+/", ' ', $_location)); /* To my understanding we're not allowed to use \IPS\Geolocation, as that uses Google API, and we're not showing the info on a Google Map. */ $nominatim = \IPS\membermap\Map::i()->getLatLng($_location); if (is_array($nominatim) and count($nominatim)) { $lat = $nominatim['lat']; $lng = $nominatim['lng']; $location = $nominatim['location']; } } if ($lat and $lng) { $marker = \IPS\membermap\Markers\Markers::createItem($_member, NULL, new \IPS\DateTime(), \IPS\membermap\Markers\Groups::load($memberMarkerGroupId), FALSE); $marker->name = $_member->name; $marker->lat = $lat; $marker->lon = $lng; $marker->location = $location ?: $_location; $marker->save(); /* Add to index */ \IPS\Content\Search\Index::i()->index($marker); $counter++; } } } catch (\UnderflowException $e) { } catch (\RuntimeException $e) { \IPS\Log::log(array($e->getMessage(), $nominatim), 'membermap'); } catch (\Exception $e) { \IPS\Log::log(array($e->getMessage(), $nominatim), 'membermap'); throw new \IPS\Task\Exception($this, $e->getMessage()); } if ($counter > 0) { $foundRows = $members->count(); return "Synchronised {$counter} out of {$foundRows} member locations"; } else { $this->enabled = FALSE; $this->save(); /* Turn the setting off as well */ \IPS\Db::i()->update('core_sys_conf_settings', array('conf_value' => 0), array('conf_key=?', 'membermap_syncLocationField')); unset(\IPS\Data\Store::i()->settings); return; } return NULL; }