/** * Sync the search index fields of every model on the system. * * @return int */ public function syncSearchIndex(){ // Admin-only page. if(!\Core\user()->checkAccess('g:admin')){ return View::ERROR_ACCESSDENIED; } // Just run through every component currently installed and reinstall it. // This will just ensure that the component is up to date and correct as per the component.xml metafile. $view = $this->getView(); $changes = []; $outoftime = false; $counter = 0; $resume = \Core\Session::Get('syncsearchresume', 1); $timeout = ini_get('max_execution_time'); // Dunno why this is returning 0, but if it is, reset it to 30 seconds! if(!$timeout) $timeout = 30; $memorylimit = ini_get('memory_limit'); if(stripos($memorylimit, 'M') !== false){ $memorylimit = str_replace(['m', 'M'], '', $memorylimit); $memorylimit *= (1024*1024); } elseif(stripos($memorylimit, 'G') !== false){ $memorylimit = str_replace(['g', 'G'], '', $memorylimit); $memorylimit *= (1024*1024*1024); } foreach(\Core::GetComponents() as $c){ /** @var Component_2_1 $c */ if($outoftime){ break; } foreach($c->getClassList() as $class => $file){ if($outoftime){ break; } if($class == 'model'){ continue; } if(strrpos($class, 'model') !== strlen($class) - 5){ // If the class doesn't explicitly end with "Model", it's also not a model. continue; } if(strpos($class, '\\') !== false){ // If this "Model" class is namespaced, it's not a valid model! // All Models MUST reside in the global namespace in order to be valid. continue; } $ref = new ReflectionClass($class); if(!$ref->getProperty('HasSearch')->getValue()){ // This model doesn't have the searchable flag, skip it. continue; } $c = ['name' => $class, 'count' => 0]; $fac = new ModelFactory($class); while(($m = $fac->getNext())){ ++$counter; if($counter < $resume){ // Allow this process to be resumed where it left off, since it may take more than 30 seconds. continue; } if(\Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->getTime() + 5 >= $timeout){ // OUT OF TIME! // Remember where this process left off and exit. \Core\Session::Set('syncsearchresume', $counter); $outoftime = true; break; } if(memory_get_usage(true) + 40485760 >= $memorylimit){ // OUT OF MEMORY! // Remember where this process left off and exit. \Core\Session::Set('syncsearchresume', $counter); $outoftime = true; break; } /** @var Model $m */ $m->set('search_index_pri', '!'); $m->save(); $c['count']++; } $changes[] = $c; } } if(!$outoftime){ // It finished! Unset the resume counter. \Core\Session::UnsetKey('syncsearchresume'); } $view->title = 'Sync Searchable Index'; $view->assign('changes', $changes); $view->assign('outoftime', $outoftime); }
<?php /** * Upgrade script to convert all the JSON-encoded user groups and transpose them to the new UserUserGroup object. * * @package Core */ $fac = new ModelFactory('UserModel'); $fac->where('groups != '); while(($user = $fac->getNext())){ /** @var UserModel $user */ // datamodel backed users have the groups listed in their column "groups". $g = json_decode($user->get('groups'), true); if(!$g) $g = array(); $gids = []; foreach($g as $gid){ if(is_array($gid)){ $gids = array_merge($gids, $gid); } else{ $gids[] = $gid; } } $gids = array_unique($gids); $user->setGroups($gids); $user->save(); }