Exemple #1
0
 /**
  * Moving member markers to the new centralised location for all markers 
  */
 public function step1()
 {
     $memberGroupId = \IPS\membermap\Map::i()->getMemberGroupId();
     $limit = 0;
     $did = 0;
     $perCycle = 500;
     if (isset(\IPS\Request::i()->extra)) {
         $limit = (int) \IPS\Request::i()->extra;
     }
     /* Try to prevent timeouts to the extent possible */
     $cutOff = \IPS\core\Setup\Upgrade::determineCutoff();
     foreach (\IPS\Db::i()->select('mm.*, m.name, m.members_seo_name', array('membermap_members', 'mm'), '', 'mm.member_id ASC', array($limit, $perCycle))->join(array('core_members', 'm'), 'mm.member_id=m.member_id') as $member) {
         if ($cutOff !== null and time() >= $cutOff) {
             return $limit + $did;
         }
         $did++;
         /* We don't have a name, likely this member has been deleted */
         if ($member['name'] == '' or $member['name'] == NULL) {
             continue;
         }
         \IPS\Db::i()->insert('membermap_markers', array('marker_parent_id' => $memberGroupId, 'marker_name' => $member['name'], 'marker_name_seo' => $member['members_seo_name'], 'marker_lat' => $member['lat'], 'marker_lon' => $member['lon'], 'marker_member_id' => $member['member_id'], 'marker_added' => $member['marker_date'] ?: time()));
     }
     if ($did) {
         return $limit + $did;
     } else {
         unset($_SESSION['_step1Count']);
         return TRUE;
     }
 }
Exemple #2
0
 /**
  * Run Background Task
  *
  * @param	mixed					$data	Data as it was passed to \IPS\Task::queue()
  * @param	int						$offset	Offset
  * @return	int|null				New offset or NULL if complete
  * @throws	\OutOfRangeException	Indicates offset doesn't exist and thus task is complete
  */
 public function run($data, $offset)
 {
     $currentMemUsage = memory_get_usage(TRUE);
     /* Wipe out the old files on the first run */
     if ($offset === 0) {
         \IPS\membermap\Map::i()->deleteCacheFiles();
     }
     $count = 0;
     $memberMarkers = array();
     $customMarkers = array();
     $selectColumns = array('mm.*', 'mg.*', 'm.member_id', 'm.name', 'm.members_seo_name', 'm.member_group_id', 'm.pp_photo_type', 'm.pp_main_photo', 'm.pp_thumb_photo');
     if (\IPS\Settings::i()->allow_gravatars) {
         $selectColumns[] = 'm.pp_gravatar';
         $selectColumns[] = 'm.email';
         $selectColumns[] = 'm.members_bitoptions';
     }
     /* Remember to update membermap\Map too */
     $_markers = \IPS\Db::i()->select(implode(',', $selectColumns), array('membermap_markers', 'mm'), array('marker_open=1'), 'mg.group_position ASC, mm.marker_id DESC', array($offset, $this->perCycle))->join(array('membermap_markers_groups', 'mg'), 'mm.marker_parent_id=mg.group_id')->join(array('core_members', 'm'), 'mm.marker_member_id=m.member_id');
     foreach ($_markers as $marker) {
         $count++;
         if ($marker['group_type'] == 'member') {
             $memberMarkers[] = $marker;
         } else {
             $customMarkers[] = $marker;
         }
     }
     if ($count > 0) {
         $markers = \IPS\membermap\Map::i()->formatMemberMarkers($memberMarkers);
         $custMarkers = \IPS\membermap\Map::i()->formatCustomMarkers($customMarkers);
         $markers = array_merge($markers, $custMarkers);
         $fileNumber = $offset / $this->perCycle;
         touch(\IPS\ROOT_PATH . '/datastore/membermap_cache/membermap-' . $fileNumber . '.json');
         chmod(\IPS\ROOT_PATH . '/datastore/membermap_cache/membermap-' . $fileNumber . '.json', \IPS\IPS_FILE_PERMISSION);
         \file_put_contents(\IPS\ROOT_PATH . '/datastore/membermap_cache/membermap-' . $fileNumber . '.json', json_encode(array('markers' => $markers, 'memUsage' => (memory_get_usage(TRUE) - $currentMemUsage) / 1024 . 'kB', 'fromQueue' => 1)));
         /* Store the timestamp of the cache to force the browser to purge its local storage */
         \IPS\Data\Store::i()->membermap_cacheTime = time();
     }
     if (!$count) {
         throw new \IPS\Task\Queue\OutOfRangeException();
     }
     return $offset + $count;
 }
Exemple #3
0
 /**
  * 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;
                 }
             }
         }
     }
 }
Exemple #4
0
 /**
  * Delete a marker
  *
  * @return	void
  */
 protected function delete()
 {
     \IPS\Session::i()->csrfCheck();
     if (!\IPS\Member::loggedIn()->member_id or !intval(\IPS\Request::i()->member_id)) {
         \IPS\Output::i()->error('no_permission', '2MM3/4', 403, '');
     }
     /* Get the marker */
     $existing = \IPS\membermap\Map::i()->getMarkerByMember(intval(\IPS\Request::i()->member_id), FALSE);
     if (isset($existing)) {
         $is_supmod = \IPS\Member::loggedIn()->modPermission() ?: 0;
         if ($is_supmod or $existing->mapped('author') == \IPS\Member::loggedIn()->member_id and $existing->canDelete()) {
             $existing->delete();
             \IPS\Output::i()->json('OK');
         }
     }
     /* Fall back to a generic error */
     \IPS\Output::i()->error('no_permission', '2MM3/5', 403, '');
 }
Exemple #5
0
 /**
  * Delete data
  *
  * @return void
  */
 public function delete()
 {
     /* Can't delete a protected group */
     if ($this->protected) {
         throw new \DomainException('No no no no no');
     }
     parent::delete();
     \IPS\membermap\Map::i()->invalidateJsonCache();
 }
Exemple #6
0
 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;
 }
Exemple #7
0
 /**
  * Delete data
  *
  * @return void
  */
 public function delete()
 {
     parent::delete();
     $this->container()->setLastComment();
     $this->container()->save();
     \IPS\membermap\Map::i()->invalidateJsonCache();
 }
Exemple #8
0
 /**
  * Install 'other' items.
  *
  * @return void
  */
 public function installOther()
 {
     /* Install default Members marker group */
     /* Calling this will create a group if one don't exist */
     \IPS\membermap\Map::i()->getMemberGroupId();
 }
Exemple #9
0
 /**
  * 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;
 }