public function run($mode = 'test')
 {
     $testMode = $mode == 'test';
     $message = "";
     $projectlist = new ProjectListModel();
     $projectlist->read();
     $projectIds = array_map(function ($e) {
         return $e['id'];
     }, $projectlist->entries);
     $projectsChanged = 0;
     foreach ($projectlist->entries as $projectParams) {
         // foreach existing project
         $projectId = $projectParams['id'];
         $project = new ProjectModel($projectId);
         if ($project->siteName == '') {
             $sfproject = new SfchecksProjectModel($projectId);
             $sfproject->themeName = "jamaicanpsalms";
             $message .= "Changed the " . $sfproject->projectName . " to be a sfchecks/scriptureforge project with jamaican psalms theme\n";
             if (!$testMode) {
                 $sfproject->write();
             }
             $projectsChanged++;
         }
     }
     if ($projectsChanged > 0) {
         $message .= "\n\nChanged {$projectsChanged} projects to be of sfchecks type under scriptureforge and jamaicanpsalms theme \n\n";
     } else {
         $message .= "\n\nNo projects were found/changed \n\n";
     }
     return $message;
 }
 public function run()
 {
     $message = '';
     $projectList = new ProjectListModel();
     $projectList->read();
     $projectIds = array_map(function ($e) {
         return $e['id'];
     }, $projectList->entries);
     $emptyQuestionTitles = 0;
     foreach ($projectIds as $projectId) {
         $project = new ProjectModel($projectId);
         $activityEntries = ActivityListDto::getActivityForProject($project);
         foreach ($activityEntries as $activity) {
             if (key_exists('questionRef', $activity) && key_exists('question', $activity['content'])) {
                 $questionId = $activity['questionRef'];
                 $questionTitle = $activity['content']['question'];
                 if ($questionTitle == '') {
                     $emptyQuestionTitles++;
                     $questionModel = new QuestionModel($project, $questionId);
                     $activityModel = new ActivityModel($project, $activity['id']);
                     $newTitle = $questionModel->getTitleForDisplay();
                     $activityModel->actionContent['question'] = $newTitle;
                     $message .= "Fixing activity " . $activity['action'] . " with title '" . $newTitle . "'\n";
                     $activityModel->write();
                 }
             }
         }
     }
     if ($emptyQuestionTitles > 0) {
         $message .= "\n\nFixed up {$emptyQuestionTitles} empty question titles in the activity log\n\n";
     } else {
         $message .= "\n\nNo empty question titles were found in the activity log \n\n";
     }
     return $message;
 }
 public static function run($mode = 'test')
 {
     $testMode = $mode != 'run';
     print "Fix MultiParagraph data structure and config.\n";
     $projectList = new ProjectListModel();
     $projectList->read();
     $totalProjectCount = $projectList->count;
     $skippedProjects = 0;
     $projectCount = 0;
     foreach ($projectList->entries as $projectParams) {
         $projectId = $projectParams['id'];
         $project = new LexProjectModelForUseWithMultiParagraphMigration($projectId);
         if ($project->appName == 'lexicon' && !$project->hasHadMultiParagraphsMigrated) {
             if (!$project->hasSendReceive()) {
                 print "\n-------------  {$project->projectName}.\n";
                 $projectCount++;
                 self::analyzeProject($project, $testMode);
             } else {
                 $skippedProjects++;
             }
         } else {
             $skippedProjects++;
         }
         unset($project);
         if ($projectCount >= 1) {
             print "\nProcessed projects " . ($skippedProjects + 1) . " - " . ($skippedProjects + $projectCount) . " of {$totalProjectCount} projects\n";
             break;
         }
     }
     if ($skippedProjects > 0) {
         print "Skipped {$skippedProjects} projects\n";
     }
 }
 public static function run($mode = 'test')
 {
     $testMode = $mode != 'run';
     print "Fix Entry guids.\n";
     $projectList = new ProjectListModel();
     $projectList->read();
     $totalProjectCount = $projectList->count;
     $skippedProjects = 0;
     $projectCount = 0;
     foreach ($projectList->entries as $projectListItem) {
         $project = new LexProjectModelForEntryGuidMigration($projectListItem['id']);
         if ($project->appName == 'lexicon' && !$project->hasHadEntryGuidMigrated && !$project->hasSendReceive()) {
             print "\n-------------  {$project->projectName}\n";
             $projectCount++;
             self::analyzeProject($project, $testMode);
         } else {
             $skippedProjects++;
         }
         unset($project);
         if ($projectCount >= 1) {
             print "\nProcessed projects " . ($skippedProjects + 1) . " - " . ($skippedProjects + $projectCount) . " of {$totalProjectCount} projects\n";
             break;
         }
     }
     if ($skippedProjects > 0) {
         print "Skipped {$skippedProjects} projects\n";
     }
 }
 public function testProjectList_HasCountAndEntries()
 {
     $model = new ProjectListModel();
     $model->read();
     $this->assertNotEquals(0, $model->count);
     $this->assertNotNull($model->entries);
 }
 public function run($userId, $mode = 'test')
 {
     $testMode = $mode != 'run';
     $message = "Ensure DB Indexes\n";
     $numberOfIndexesCreated = 0;
     $website = Website::get();
     $onDevMachine = strpos($website->domain, 'dev.') !== false;
     $onLocalMachine = strrpos($website->domain, '.local') !== false;
     $message .= "\n-------------  Main Database:\n";
     $mainCollectionName = ProjectModelMongoMapper::instance()->getCollectionName();
     $mainIndexes = ProjectModelMongoMapper::instance()->INDEXES_REQUIRED;
     $mainIndexesToCreate = MongoStore::getIndexesNotSetInCollection(SF_DATABASE, $mainCollectionName, $mainIndexes);
     $numberOfIndexesCreated += count($mainIndexesToCreate);
     $message .= count($mainIndexesToCreate) . " main indexes created.\n";
     if (($onDevMachine || $onLocalMachine) && MongoStore::hasDB(SF_TEST_DATABASE)) {
         $message .= "\n-------------  Test Database:\n";
         $mainIndexesToCreate = MongoStore::getIndexesNotSetInCollection(SF_TEST_DATABASE, $mainCollectionName, $mainIndexes);
         $numberOfIndexesCreated += count($mainIndexesToCreate);
         $message .= count($mainIndexesToCreate) . " test indexes created.\n";
     }
     if (!$testMode) {
         MongoStore::ensureIndexesInCollection(SF_DATABASE, $mainCollectionName, $mainIndexes);
         if (($onDevMachine || $onLocalMachine) && MongoStore::hasDB(SF_TEST_DATABASE)) {
             MongoStore::ensureIndexesInCollection(SF_TEST_DATABASE, $mainCollectionName, $mainIndexes);
         }
     }
     // loop over every project
     $projectList = new ProjectListModel();
     $projectList->read();
     foreach ($projectList->entries as $projectParams) {
         $project = ProjectModel::getById($projectParams['id']);
         if ($project->appName == 'lexicon') {
             $message .= "\n-------------  {$project->projectName} project:\n";
             $lexiconCollectionName = LexEntryModel::mapper($project->databaseName())->getCollectionName();
             $lexiconIndexes = LexEntryModel::mapper($project->databaseName())->INDEXES_REQUIRED;
             $lexiconIndexesToCreate = MongoStore::getIndexesNotSetInCollection($project->databaseName(), $lexiconCollectionName, $lexiconIndexes);
             $numberOfIndexesCreated += count($lexiconIndexesToCreate);
             $optionListCollectionName = LexOptionListModel::mapper($project->databaseName())->getCollectionName();
             $optionListIndexes = LexOptionListModel::mapper($project->databaseName())->INDEXES_REQUIRED;
             $optionListIndexesToCreate = MongoStore::getIndexesNotSetInCollection($project->databaseName(), $optionListCollectionName, $optionListIndexes);
             $numberOfIndexesCreated += count($optionListIndexesToCreate);
             if (count($lexiconIndexesToCreate) + count($optionListIndexesToCreate) > 0) {
                 $message .= count($lexiconIndexesToCreate) . " lexicon indexes created.\n";
                 $message .= count($optionListIndexesToCreate) . " option list indexes created.\n";
             } else {
                 $message .= "No indexes needed creating.\n";
             }
             if (!$testMode) {
                 MongoStore::ensureIndexesInCollection($project->databaseName(), $lexiconCollectionName, $lexiconIndexes);
                 MongoStore::ensureIndexesInCollection($project->databaseName(), $optionListCollectionName, $optionListIndexes);
             }
         }
     }
     if ($numberOfIndexesCreated > 0) {
         $message .= "\nCreated {$numberOfIndexesCreated} DB Indexes.\n\n";
     } else {
         $message .= "\nAll indexes were present.\n\n";
     }
     return $message;
 }
 public function testProjectList_HadOnlyProjects()
 {
     $projectList = new ProjectListModel();
     $projectList->read();
     foreach ($projectList->entries as $entry) {
         $this->assertArrayHasKey('projectName', $entry);
     }
 }
 public static function run($mode = 'test')
 {
     $testMode = $mode != 'run';
     print "Fix Meaning->Definition and Example->Sentence labels.\n";
     $projectlist = new ProjectListModel();
     $projectlist->read();
     $fixCount = 0;
     $definitionLabelsUpdated = 0;
     $sentenceLabelsUpdated = 0;
     foreach ($projectlist->entries as $projectParams) {
         // foreach existing project
         $projectId = $projectParams['id'];
         $project = new ProjectModel($projectId);
         if ($project->appName == 'lexicon') {
             $project = new LexProjectModel($projectId);
             $projectChanged = false;
             $entryFieldsArray = $project->config->entry->fields->getArrayCopy();
             if (array_key_exists("senses", $entryFieldsArray)) {
                 $senseFieldsArray = $entryFieldsArray["senses"]->fields->getArrayCopy();
                 if ($senseFieldsArray["definition"]->label != "Definition") {
                     $senseFieldsArray["definition"]->label = "Definition";
                     //print "  Fixed \"Definition\" label\n";
                     $definitionLabelsUpdated++;
                     $projectChanged = true;
                 }
                 if (array_key_exists("examples", $senseFieldsArray)) {
                     $exampleFieldsArray = $senseFieldsArray["examples"]->fields->getArrayCopy();
                     if ($exampleFieldsArray["sentence"]->label != "Sentence") {
                         $exampleFieldsArray["sentence"]->label = "Sentence";
                         //print "  Fixed \"Sentence\" label\n";
                         $sentenceLabelsUpdated++;
                         $projectChanged = true;
                     }
                 }
             }
             $senseFieldsArray["examples"]->fields->exchangeArray($exampleFieldsArray);
             $entryFieldsArray["senses"]->fields->exchangeArray($senseFieldsArray);
             $project->config->entry->fields->exchangeArray($entryFieldsArray);
             if ($projectChanged) {
                 $fixCount++;
                 if (!$testMode) {
                     print "  Saving changes to project {$project->projectName}.\n";
                     $project->write();
                 }
             }
             unset($exampleFieldsArray);
             unset($senseFieldsArray);
             unset($entryFieldsArray);
         }
     }
     if ($fixCount > 0) {
         print "{$fixCount} projects were fixed\n";
         print "{$definitionLabelsUpdated} \"meaning\" labels changed to \"definition\"\n";
         print "{$sentenceLabelsUpdated} \"example\" labels changed to \"sentence\"\n";
     } else {
         print "No projects needed fixing\n";
     }
 }
 public function run($userId, $mode = 'test')
 {
     $testMode = $mode != 'run';
     $message = "Fix site roles integrity\n\n";
     // loop over every project
     $projectlist = new ProjectListModel();
     $projectlist->read();
     $fixCount = array();
     $userNoRoleCount = 0;
     foreach ($projectlist->entries as $projectParams) {
         // foreach existing project
         $projectId = $projectParams['id'];
         $project = new ProjectModel($projectId);
         $hostname = $project->siteName;
         $website = Website::get($hostname);
         $fixCount[$hostname] = 0;
         $projectUserRefs = array_keys($project->users->getArrayCopy());
         //$message .= "-------------  " . $project->projectName . "\n";
         foreach ($projectUserRefs as $userId) {
             // foreach user that is a member of this project
             $user = new UserModel($userId);
             if (!array_key_exists($hostname, $user->siteRole) && $user->username != '') {
                 $message .= "Fixed user '" . $user->username . "' who did not have a site role on " . $hostname . "\n";
                 $fixCount[$hostname]++;
                 $user->siteRole[$hostname] = $website->userDefaultSiteRole;
                 if (!$testMode) {
                     $user->write();
                 }
             }
         }
     }
     // loop over users who do not belong to any projects
     $userlist = new UserListModel();
     $userlist->read();
     foreach ($userlist->entries as $userParams) {
         // foreach existing user
         $userId = $userParams['id'];
         $user = new UserModel($userId);
         if (count($user->projects->refs) == 0 && count(array_keys($user->siteRole->getArrayCopy())) == 0) {
             $userNoRoleCount++;
             //$message .= "Warning: user '" . $user->username . "' has no projects and no siteRoles on any site!\n";
         }
     }
     foreach ($fixCount as $site => $count) {
         if ($count > 0) {
             $message .= "\n\n{$site} : Fixed {$count} non-existent site roles \n\n";
         } else {
             $message .= "\n\n{$site} : Nothing to do \n\n";
         }
     }
     if ($userNoRoleCount > 0) {
         $message .= "Warning: {$userNoRoleCount} useless users had no projects and no siteRoles on any site!\n";
     }
     return $message;
 }
 public function run($mode = 'test')
 {
     $testMode = $mode == 'test';
     $message = "";
     $userlist = new UserListModel();
     $userlist->read();
     $badUserRoles = 0;
     foreach ($userlist->entries as $userParams) {
         // foreach existing user
         $userId = $userParams['id'];
         $user = new UserModel($userId);
         if (!$user->role) {
             $user->role = SystemRoles::USER;
             if (!$testMode) {
                 $user->write();
             }
             $badUserRoles++;
             $message .= "Fixed role of user {$userId}\n";
         }
     }
     if ($badUserRoles > 0) {
         $message .= "\n\nFixed {$badUserRoles} non-existent user roles from the users collection\n\n";
     } else {
         $message .= "\n\nNo non-existent user roles found in the users collection\n\n";
     }
     $projectlist = new ProjectListModel();
     $projectlist->read();
     $badProjectUserRoles = 0;
     foreach ($projectlist->entries as $projectParams) {
         // foreach existing project
         $projectId = $projectParams['id'];
         $project = new ProjectModel($projectId);
         $projectUserRefs = array_keys($project->users);
         foreach ($projectUserRefs as $ref) {
             // foreach user that is a member of this project
             if (!isset($project->users[$ref]->role)) {
                 $project->users[$ref]->role = ProjectRoles::CONTRIBUTOR;
                 $badProjectUserRoles++;
                 $message .= "Fixed role of user {$ref} for project {$projectId}\n";
             }
         }
         if (!$testMode) {
             $project->write();
         }
     }
     if ($badProjectUserRoles > 0) {
         $message .= "\n\nFixed {$badProjectUserRoles} non-existent user roles from the projects collection\n\n";
     } else {
         $message .= "\n\nNo non-existent user roles found in the projects collection\n\n";
     }
     return $message;
 }
 public static function encode()
 {
     $data = array();
     $listModel = new ProjectListModel();
     $listModel->read();
     $projects = array();
     foreach ($listModel->entries as $p) {
         $project = new SemDomTransProjectModel($p["id"]);
         if ($project->appName == LfProjectModel::SEMDOMTRANS_APP && $project->languageIsoCode != "en") {
             $projects[] = array('name' => $project->languageIsoCode, 'id' => $p['id']);
         }
     }
     $data['languages'] = $projects;
     return $data;
 }
 /**
  * Gets list of currently open projects for a user (excluding those he is part of are has submitted a join request for)
  * @param string $userId
  * @return multitype:\Api\Model\Languageforge\SemDomTransProjectModel
  */
 public static function getOpenSemdomProjects($userId)
 {
     $projects = new ProjectListModel();
     $projects->read();
     $semdomProjects = [];
     foreach ($projects->entries as $p) {
         $project = new ProjectModel($p["id"]);
         if ($project->appName == LfProjectModel::SEMDOMTRANS_APP && !array_key_exists($userId, $project->users) && !array_key_exists($userId, $project->userJoinRequests)) {
             $sp = new SemDomTransProjectModel($p["id"]);
             if ($sp->languageIsoCode != "en") {
                 $semdomProjects[] = $sp;
             }
         }
     }
     return $semdomProjects;
 }
 public function run($mode = 'test')
 {
     $testMode = $mode != 'run';
     $message = "";
     $templateList = new GlobalQuestionTemplateListModel();
     $templateList->read();
     if (count($templateList->entries) > 0) {
     } else {
         $message .= "There are no global templates to migrate\n\n";
     }
     $templatesMoved = 0;
     $projectlist = new ProjectListModel();
     $projectlist->read();
     $project = null;
     foreach ($projectlist->entries as $projectParams) {
         // foreach existing project
         $projectId = $projectParams['id'];
         $p = new SfchecksProjectModel($projectId);
         if ($p->databaseName() == 'sf_jamaican_psalms') {
             $project = $p;
         }
     }
     if (!is_null($project)) {
         $message .= "Migrating global templates to the '" . $project->projectName . "' project\n\n";
         foreach ($templateList->entries as $globalTemplate) {
             $template = new QuestionTemplateModel($project);
             $template->title = $globalTemplate['title'];
             $template->description = $globalTemplate['description'];
             $message .= "Moving '" . $template->title . "'\n";
             if (!$testMode) {
                 $template->write();
                 $gt = new GlobalQuestionTemplateModel($globalTemplate['id']);
                 $gt->remove();
             }
             $templatesMoved++;
         }
         $message .= "\n\nMoved {$templatesMoved} global templates to the specified project\n\n";
     } else {
         $message .= "Error: cound not find the Jamaican Psalms project on this server\n\n";
     }
     return $message;
 }
 public function run($mode = 'test')
 {
     $testMode = $mode != 'run';
     $message = "";
     $projectlist = new ProjectListModel();
     $projectlist->read();
     $contribRoleUpdated = 0;
     $managerRoleUpdated = 0;
     foreach ($projectlist->entries as $projectParams) {
         // foreach existing project
         $projectId = $projectParams['id'];
         $project = new SfchecksProjectModel($projectId);
         $users = $project->users;
         foreach ($users as $userId => $rm) {
             $role = $rm->role;
             if ($role == 'user') {
                 $roleModel = new ProjectRoleModel();
                 $roleModel->role = 'contributor';
                 $project->users[$userId] = $roleModel;
                 $contribRoleUpdated++;
                 $message .= "Updated user role for user {$userId}\n";
             } elseif ($role == 'project_admin') {
                 $roleModel = new ProjectRoleModel();
                 $roleModel->role = 'project_manager';
                 $project->users[$userId] = $roleModel;
                 $message .= "Updated manager role for user {$userId}\n";
                 $managerRoleUpdated++;
             }
         }
         if (!$testMode) {
             $message .= "saving project {$projectId}\n";
             $project->write();
         }
     }
     if ($contribRoleUpdated > 0 || $managerRoleUpdated) {
         $message .= "\n\nChanged {$contribRoleUpdated} user roles to be 'contributor' and {$managerRoleUpdated} project_admin roles to be 'project_manager'\n\n";
     } else {
         $message .= "\n\nNo old roles were found/changed \n\n";
     }
     return $message;
 }
 public function run($userId, $mode = 'test')
 {
     $testMode = $mode != 'run';
     $message = "Remove Environment and Reversal Entries from field order config\n\n";
     // Note: LF projects that don't have config data in mongo will use the default PHP model.
     // In these cases, the migration script won't find these field orders to remove, so nothing gets written out
     $projectlist = new ProjectListModel();
     $projectlist->read();
     $projectsAffected = 0;
     foreach ($projectlist->entries as $projectParams) {
         // foreach existing project
         $projectId = $projectParams['id'];
         $project = new ProjectModel($projectId);
         if ($project->appName == 'lexicon') {
             $project = new LexProjectModel($projectId);
             $fieldOrderUpdated = 0;
             $this->RemoveFromArray("environments", $project->config->entry->fieldOrder, $message, $fieldOrderUpdated);
             $fieldsArray = $project->config->entry->fields->getArrayCopy();
             if (array_key_exists("senses", $fieldsArray)) {
                 $this->RemoveFromArray("reversalEntries", $fieldsArray["senses"]->fieldOrder, $message, $fieldOrderUpdated);
                 $project->config->entry->fields->exchangeArray($fieldsArray);
             }
             if ($fieldOrderUpdated > 0) {
                 $projectsAffected++;
                 $message .= "\tRemoved: {$fieldOrderUpdated} field orders from {$project->projectName}\n";
                 if (!$testMode) {
                     $message .= "\tSaving changes to project {$project->projectName}.\n\n";
                     $project->write();
                 }
             }
         }
         unset($project);
     }
     if ($projectsAffected > 0) {
         $message .= "{$projectsAffected} projects were fixed\n";
     } else {
         $message .= "No projects needed fixing\n";
     }
     return $message;
 }
 public function run($userId, $mode = 'test')
 {
     ini_set('max_execution_time', 300);
     // Sufficient time to update semdom keys for every project
     $testMode = $mode == 'test';
     $message = "Fix SemanticDomain Keys to only store numeric keys (like 1.1.1) \n";
     $projectlist = new ProjectListModel();
     $projectlist->read();
     // Because of the memory needed to process semdom keys for projects, we'll limit the
     // migration script to run in batches of this many projects per run.
     $maxNumProjects = 1;
     $lfProjectCount = 0;
     // Counter of LF projects analyzed
     $skippedProjects = 0;
     $totalProjectCount = $projectlist->count;
     foreach ($projectlist->entries as $projectParams) {
         $projectId = $projectParams['id'];
         $project = new ProjectModelForUseWithSemanticDomainMigration($projectId);
         if ($project->appName == 'lexicon' && !$project->hasMigratedSemanticDomainKeys) {
             print "\n-------------  {$project->projectName}.";
             print "\n";
             $lfProjectCount++;
             $this->analyzeProject($project, $projectId, $testMode, $message);
             print "Memory usage: " . $this->getMemoryUsage() . "\n";
         } else {
             $skippedProjects++;
         }
         // Summary
         if ($lfProjectCount >= $maxNumProjects) {
             print "Processed projects " . ($skippedProjects + 1) . " - " . ($skippedProjects + $lfProjectCount) . " of {$totalProjectCount} projects\n";
             break;
         }
     }
     // foreach project
     if ($skippedProjects > 0) {
         print "Skipped {$skippedProjects} projects\n";
     }
     return $message;
 }
 public static function run($mode = 'test')
 {
     ini_set('max_execution_time', 300);
     // Sufficient time to update for every project
     $testMode = $mode == 'test';
     print "Fix Sense, Example and Picture guids.\n";
     $projectList = new ProjectListModel();
     $projectList->read();
     $totalProjectCount = $projectList->count;
     // Because of the time needed to process projects, we'll limit the
     // migration script to run in batches of this many projects per run.
     $maxNumProjects = 1;
     $skippedProjects = 0;
     $lfProjectCount = 0;
     foreach ($projectList->entries as $projectParams) {
         $projectId = $projectParams['id'];
         $project = new LexProjectModelForUseWithSenseGuidMigration($projectId);
         if ($project->appName == 'lexicon' && !$project->hasHadSenseGuidsMigrated) {
             if (!$project->hasSendReceive()) {
                 print "\n-------------  {$project->projectName}.\n";
                 $lfProjectCount++;
                 self::analyzeProject($project, $projectId, $testMode);
             } else {
                 continue;
             }
         } else {
             $skippedProjects++;
         }
         unset($project);
         if ($lfProjectCount >= $maxNumProjects) {
             print "\nProcessed projects " . ($skippedProjects + 1) . " - " . ($skippedProjects + $lfProjectCount) . " of {$totalProjectCount} projects\n";
             break;
         }
     }
     if ($skippedProjects > 0) {
         print "Skipped {$skippedProjects} projects\n";
     }
 }
 public function run($userId, $mode = 'test')
 {
     $testMode = $mode != 'run';
     $message = "Fix project site name integrity\n\n";
     // loop over every project
     $projectlist = new ProjectListModel();
     $projectlist->read();
     $fixCount = 0;
     foreach ($projectlist->entries as $projectParams) {
         // foreach existing project
         $projectId = $projectParams['id'];
         $project = new ProjectModel($projectId);
         $hostname = $project->siteName;
         $website = Website::get($hostname);
         if (!$website) {
             // the website does not exist anymore
             $message .= "{$hostname} does not exist anymore...";
             // see if there is a redirect
             $redirect = Website::getRawRedirect($hostname);
             if ($redirect) {
                 $message .= "changed to {$redirect}\n";
                 $project->siteName = $redirect;
                 $fixCount++;
                 if (!$testMode) {
                     $project->write();
                 }
             } else {
                 $message .= "ERROR: dont know what to change it to since no redirect is available\n";
             }
         }
     }
     if ($fixCount > 0) {
         $message .= "\n\nFixed siteNames in {$fixCount} project(s)\n\n";
     } else {
         $message .= "\n\nNo non-existent siteNames were found in the projects collection\n\n";
     }
     return $message;
 }
<?php

require_once 'scriptsConfig.php';
use Api\Model\Shared\DbIntegrityHelper;
use Api\Model\Shared\ProjectListModel;
php_sapi_name() == 'cli' or die('this script must be run on the command-line');
$runForReal = false;
if (count($argv) > 1 && $argv[1] == 'run') {
    $runForReal = true;
}
$helper = new DbIntegrityHelper($runForReal);
$projectList = new ProjectListModel();
$projectList->read();
foreach ($projectList->entries as $p) {
    $helper->checkProject($p['id']);
    print $helper->flushOutput();
}
print $helper->flushOutput();
// verify integrity of all users
// verify integrity of all sites
// list sites and which projects are in which sites
 /**
  * @return ProjectListModel
  */
 public static function listProjects()
 {
     $list = new ProjectListModel();
     $list->read();
     return $list;
 }
 public function run($mode = 'test')
 {
     $testMode = $mode == 'test';
     $message = "";
     $userlist = new UserListModel();
     $userlist->read();
     $userIds = array_map(function ($e) {
         return $e['id'];
     }, $userlist->entries);
     $projectlist = new ProjectListModel();
     $projectlist->read();
     $projectIds = array_map(function ($e) {
         return $e['id'];
     }, $projectlist->entries);
     $deadProjectLinks = 0;
     foreach ($userlist->entries as $userParams) {
         // foreach existing user
         $userId = $userParams['id'];
         $user = new UserModel($userId);
         $userProjectRefs = $user->projects->refs;
         foreach ($userProjectRefs as $ref) {
             // foreach project the user belongs to
             if (!in_array($ref, $projectIds)) {
                 $user->removeProject($ref);
                 // remove dead project link
                 $deadProjectLinks++;
                 $message .= "Removed dead project link {$ref} from user {$userId}\n";
             }
         }
         if (!$testMode) {
             $user->write();
         }
     }
     if ($deadProjectLinks > 0) {
         $message .= "\n\nRemoved {$deadProjectLinks} dead project links from the users collection\n\n";
     } else {
         $message .= "\n\nNo dead project links were found\n\n";
     }
     $deadUserLinks = 0;
     foreach ($projectlist->entries as $projectParams) {
         // foreach existing project
         $projectId = $projectParams['id'];
         $project = new ProjectModel($projectId);
         $projectUserRefs = array_keys($project->users);
         foreach ($projectUserRefs as $ref) {
             // foreach user that is a member of this project
             if (!in_array($ref, $userIds)) {
                 $project->removeUser($ref);
                 // remove dead user link
                 $deadUserLinks++;
                 $message .= "Removed dead user link {$ref} for project {$projectId}\n";
             }
         }
         if (!$testMode) {
             $project->write();
         }
     }
     if ($deadUserLinks > 0) {
         $message .= "\n\nRemoved {$deadUserLinks} dead user links from the projects collection\n\n";
     } else {
         $message .= "\n\nNo dead user links were found\n\n";
     }
     return $message;
 }
 /**
  * @return UserListModel
  */
 public static function listUsers()
 {
     $list = new UserListModel();
     $list->read();
     $projectListModel = new ProjectListModel();
     $projectListModel->read();
     $projectList = array();
     foreach ($projectListModel->entries as $p) {
         $projectList[$p['id']] = $p;
     }
     foreach ($list->entries as $key => $item) {
         if (array_key_exists('projects', $item)) {
             $projectIds = $item['projects'];
             $list->entries[$key]['projects'] = array();
             foreach ($projectIds as $id) {
                 $list->entries[$key]['projects'][] = $projectList[(string) $id];
             }
         }
     }
     // Default sort on username (currently needed to sort on Site Admin because MongoDB doesn't do case insensitive sorts)
     usort($list->entries, function ($a, $b) {
         $sortOn = 'username';
         if (array_key_exists($sortOn, $a) && array_key_exists($sortOn, $b)) {
             return strtolower($a[$sortOn]) > strtolower($b[$sortOn]) ? 1 : -1;
         } else {
             return 0;
         }
     });
     return $list;
 }
 public function run($mode = 'test')
 {
     $testMode = $mode != 'run';
     $message = "";
     $projectlist = new ProjectListModel();
     $projectlist->read();
     $textsExamined = 0;
     $textsUpdated = 0;
     // foreach existing project
     foreach ($projectlist->entries as $projectParams) {
         $projectId = $projectParams['id'];
         if ($projectParams['projectName'] == 'Jamaican Psalms') {
             $project = new SfchecksProjectModel($projectId);
             $textlist = new TextListModel($project);
             $textlist->read();
             // foreach text in project
             foreach ($textlist->entries as $textParams) {
                 $textsExamined++;
                 $textId = $textParams['id'];
                 $legacyText = new TextModel_sf_v0_9_18($project, $textId);
                 $fileName = '';
                 if ($legacyText->audioUrl) {
                     $text = new TextModel($project, $textId);
                     if (!$testMode) {
                         if (!$text->audioFileName) {
                             // legacy audioUrl format "assets/<projectId>/<textId>_<fileName>"
                             $fileNamePrefix = $textId . '_';
                             $pos = strpos($legacyText->audioUrl, $fileNamePrefix);
                             $text->audioFileName = substr($legacyText->audioUrl, $pos + strlen($fileNamePrefix));
                         }
                         $text->write();
                     }
                     $message .= "Changed text: {$text->title}\n";
                     $textsUpdated++;
                 }
             }
             if (!$testMode) {
                 TextModel_sf_v0_9_18::removeAudioProperty($project->databaseName());
                 $message .= "Removed 'audioUrl' property from project: {$project->projectName}\n";
             }
         }
     }
     if ($textsUpdated > 0) {
         $message .= "\n\nChanged {$textsUpdated} legacy texts to only store audio filename\n\n";
     } else {
         $message .= "\n\nNo legacy text audio were found/changed. {$textsExamined} texts examined.\n\n";
     }
     // re-arrange assets folder
     // - remove <siteName> from path for LF
     // - add <appName> to path for SF and change <projectId> in path to <projectSlug (databaseName)>
     $message .= "\n\nRe-arrange assets folder\n~~~~~~~~~~~~~~~~~~~~~~~~\n\n";
     $project = new SfchecksProjectModel();
     $assetsFolderPath = APPPATH . "assets";
     $assetsSubfolders = glob($assetsFolderPath . '/*');
     @mkdir($assetsFolderPath . '/lexicon');
     @mkdir($assetsFolderPath . '/sfchecks');
     foreach ($assetsSubfolders as $assetsSubfolder) {
         if (file_exists($assetsSubfolder) && is_dir($assetsSubfolder)) {
             $assetsSubfolderName = basename($assetsSubfolder);
             if (strpos($assetsSubfolderName, 'languageforge') !== false) {
                 $message .= "Move into lexicon: {$assetsSubfolderName}\n";
                 $oldFolderPath = $assetsSubfolder . '/lexicon';
                 $newFolderPath = $assetsFolderPath . '/lexicon';
             } elseif ($assetsSubfolderName == 'lexicon' || $assetsSubfolderName == 'sfchecks') {
                 $message .= "No change: {$assetsSubfolderName}\n";
                 $oldFolderPath = '';
                 $newFolderPath = '';
                 $assetsSubfolder = '';
             } elseif ($project->exists($assetsSubfolderName)) {
                 $message .= "Move into sfchecks: {$assetsSubfolderName}\n";
                 $oldFolderPath = $assetsSubfolder;
                 $project->read($assetsSubfolderName);
                 $projectSlug = $project->databaseName();
                 $newFolderPath = $assetsFolderPath . "/sfchecks/{$projectSlug}";
                 if (!$testMode) {
                 }
             } else {
                 $message .= "Delete: {$assetsSubfolderName}\n";
                 $oldFolderPath = '';
                 $newFolderPath = '';
             }
             if (!$testMode) {
                 if (file_exists($oldFolderPath) && is_dir($oldFolderPath)) {
                     if (!@rename($oldFolderPath, $newFolderPath)) {
                         $oldFiles = glob($oldFolderPath . '/*');
                         foreach ($oldFiles as $oldFile) {
                             $newFile = $newFolderPath . '/' . basename($oldFile);
                             rename($oldFile, $newFile);
                         }
                     }
                 }
                 if (file_exists($assetsSubfolder) && is_dir($assetsSubfolder)) {
                     $this->recursiveRemoveFolder($assetsSubfolder);
                 }
             }
         }
     }
     return $message;
 }
 public function Run($argv)
 {
     $runForReal = false;
     if (count($argv) > 1 && $argv[1] == 'run') {
         $runForReal = true;
     } else {
         print "\nUsage: FactoryReset.php <run> <DIRECTORY>\n";
         print "Run factory reset and restore mongodb and assets from DIRECTORY\n";
         print "\nTest Mode - no data will be changed\n--------------------------------\n\n";
     }
     $archivePath = count($argv) > 2 ? $argv[2] : "";
     $projectList = new ProjectListModel();
     $projectList->read();
     // remove all existing projects
     print "\n{$projectList->count} projects will be deleted\n";
     foreach ($projectList->entries as $p) {
         $project = new ProjectModel($p['id']);
         print "Deleting Project " . $project->projectName . "\n";
         if ($runForReal) {
             try {
                 $project->remove();
             } catch (\Exception $e) {
                 // don't do anything
             }
         }
     }
     // start with a fresh database
     print "\nDropping main database...\n";
     if ($runForReal) {
         MongoStore::dropAllCollections(SF_DATABASE);
     }
     print "\nDropping other dbs on the server (like test dbs)\n";
     $cmd = "mongo --quiet {$this->hostOption} --eval 'db.getMongo().getDBNames().forEach(function(i){  " . "if (i.indexOf(\"sf_\") == 0 || i.indexOf(\"scriptureforge\") == 0) { " . "print(\"Dropping \" + i); db.getSiblingDB(i).dropDatabase()}})'";
     $this->Execute($runForReal, $cmd);
     if (is_dir($archivePath)) {
         print "\nExtracting archives...\n";
         foreach (glob("{$archivePath}/*.tgz") as $filename) {
             print "Extracting {$filename}\n";
             $cmd = "tar -xzf {$filename} -C {$archivePath}";
             $this->Execute($runForReal, $cmd);
         }
         print "\nEnsure www-data has permissions...\n";
         $cmd = "sudo chgrp -R www-data {$archivePath}/var/www";
         $this->Execute($runForReal, $cmd);
         $cmd = "sudo chown -R www-data:fieldworks {$archivePath}/var/lib";
         $this->Execute($runForReal, $cmd);
         print "\nRestoring mongodb...\n";
         $mongodbBackup = $archivePath . "/mongo_backup";
         $cmd = "mongorestore {$this->hostOption} {$mongodbBackup}";
         $this->Execute($runForReal, $cmd);
         print "\nUpdating DB site names...\n";
         $this->UpdateDBSiteName($runForReal);
         print "\nRestoring assets...\n";
         $cmd = "rsync -rzlt --chmod=Dug=rwx,Fug=rw,o-rwx --group " . "--delete-during --stats --rsync-path='sudo rsync' " . "--exclude=sfchecks " . "{$archivePath}/var/www/languageforge.org/htdocs/assets/ " . "{$this->lfAssetsPath}/htdocs/assets/";
         $this->Execute($runForReal, $cmd);
         $cmd = "rsync -rzlt --chmod=Dug=rwx,Fug=rw,o-rwx --group " . "--delete-during --stats --rsync-path='sudo rsync' " . "--exclude=lexicon --exclude=semdomtrans " . "{$archivePath}/var/www/scriptureforge.org/htdocs/assets/ " . "{$this->sfAssetsPath}/htdocs/assets/";
         $this->Execute($runForReal, $cmd);
         $cmd = "sudo rm -R {$this->lfmergeSendReceivePath}/state/*";
         $this->Execute($runForReal, $cmd);
         $cmd = "sudo rm -R {$this->lfmergeSendReceivePath}/webwork/*";
         $this->Execute($runForReal, $cmd);
         $cmd = "rsync -rzlt --chmod=Dug=rwx,Fug=rw,o-rwx --group " . "--delete-during --stats --rsync-path='sudo rsync' " . "{$archivePath}{$this->lfmergeSendReceivePath} {$this->lfmergeSendReceivePath}";
         $this->Execute($runForReal, $cmd);
         print "\nCleanup extracted files...\n";
         $cmd = "sudo rm -R {$archivePath}/var";
         $this->Execute($runForReal, $cmd);
         $cmd = "sudo rm -R {$archivePath}/mongo_backup";
         $this->Execute($runForReal, $cmd);
     } else {
         print "\nCreating local user: admin password: password\n";
         if ($runForReal) {
             $scriptureforgeWebsite = Website::get('scriptureforge.org');
             $languageforgeWebsite = Website::get('languageforge.org');
             $adminUser = UserCommands::createUser(array('id' => '', 'name' => 'Admin', 'email' => '*****@*****.**', 'username' => 'admin', 'password' => 'password', 'active' => true, 'role' => SystemRoles::SYSTEM_ADMIN), $languageforgeWebsite);
         }
     }
 }
 public function run($userId, $mode = 'test')
 {
     $testMode = $mode != 'run';
     $message = "Fix Lexicon View Settings (except Environments and ReversalEntries) to default to visible\n\n";
     $fixCount = 0;
     $projectlist = new ProjectListModel();
     $projectlist->read();
     foreach ($projectlist->entries as $projectParams) {
         // foreach existing project
         $projectId = $projectParams['id'];
         $project = new ProjectModel($projectId);
         if ($project->appName == 'lexicon') {
             $project = new LexProjectModel($projectId);
             //$message .= "\nInspecting project $project->projectName.\n";
             $showFieldUpdated = 0;
             $roleShowFieldUpdated = 0;
             //$hideFieldUpdated = 0;
             $roleHideFieldUpdated = 0;
             $disabledFields = array("environments", "reversalEntries");
             foreach ($project->config->roleViews as $role => $roleView) {
                 foreach ($roleView->fields as $fieldName => $field) {
                     if (in_array($fieldName, $disabledFields)) {
                         if ($field->show) {
                             // Hide disabled fields
                             //$message .= "Hiding role $role view of $fieldName\n";
                             $field->show = false;
                             $showFieldUpdated++;
                             $roleHideFieldUpdated++;
                         }
                     } else {
                         if (!$field->show) {
                             // enable all other fields by default
                             $field->show = true;
                             $showFieldUpdated++;
                             $roleShowFieldUpdated++;
                         }
                     }
                 }
             }
             $userShowFieldUpdated = 0;
             $userHideFieldUpdated = 0;
             foreach ($project->config->userViews as $userId => $userView) {
                 foreach ($userView->fields as $fieldName => $field) {
                     if (in_array($fieldName, $disabledFields)) {
                         if ($field->show) {
                             // Hide disabled fields
                             //$message .= "Hiding user $userId view of $fieldName\n";
                             $field->show = false;
                             $showFieldUpdated++;
                             $userHideFieldUpdated++;
                         }
                     } else {
                         if (!$field->show) {
                             // enable all other fields by default
                             $field->show = true;
                             $showFieldUpdated++;
                             $userShowFieldUpdated++;
                         }
                     }
                 }
             }
             if ($showFieldUpdated > 0) {
                 $fixCount++;
                 $message .= "  Toggled {$showFieldUpdated} View Settings fields. This comprised: \n";
                 if ($roleShowFieldUpdated > 0) {
                     $message .= "   - Changed {$roleShowFieldUpdated} role-based View Settings fields to be visible.\n";
                 }
                 if ($userShowFieldUpdated > 0) {
                     $message .= "   - Changed {$userShowFieldUpdated} user-based View Settings fields to be visible.\n";
                 }
                 if ($roleHideFieldUpdated > 0) {
                     $message .= "   - Changed {$roleHideFieldUpdated} role-based View Settings fields to be invisible.\n";
                 }
                 if ($userHideFieldUpdated > 0) {
                     $message .= "   - Changed {$userHideFieldUpdated} user-based View Settings fields to be invisible.\n";
                 }
                 if (!$testMode) {
                     $message .= "  Saving changes to project {$project->projectName}.\n";
                     $project->write();
                 }
             } else {
                 //$message .= "  No invisible View Settings fields found/changed.\n";
             }
         }
     }
     if ($fixCount > 0) {
         $message .= "{$fixCount} projects were fixed\n";
     } else {
         $message .= "No projects needed fixing\n";
     }
     return $message;
 }
 public function run($mode = 'test')
 {
     $testMode = $mode == 'test';
     $message = "";
     $userList = new UserListModel();
     $userList->read();
     $userIds = array_map(function ($e) {
         return $e['id'];
     }, $userList->entries);
     $projectList = new ProjectListModel();
     $projectList->read();
     $projectIds = array_map(function ($e) {
         return $e['id'];
     }, $projectList->entries);
     $deadCommentUserRefs = 0;
     $deadAnswerUserRefs = 0;
     foreach ($projectIds as $projectId) {
         $project = new ProjectModel($projectId);
         $textList = new TextListModel($project);
         $textList->read();
         $textIds = array_map(function ($e) {
             return $e['id'];
         }, $textList->entries);
         foreach ($textIds as $textId) {
             $questionList = new QuestionListModel($project, $textId);
             $questionList->read();
             $questionIds = array_map(function ($e) {
                 return $e['id'];
             }, $questionList->entries);
             foreach ($questionIds as $questionId) {
                 $question = new QuestionModel($project, $questionId);
                 foreach ($question->answers as $answerId => $answer) {
                     foreach ($answer->comments as $commentId => $comment) {
                         /** @var IdReference $ref */
                         $ref = $comment->userRef;
                         if (!empty($ref->id) && !in_array($ref->asString(), $userIds)) {
                             $comment->userRef->id = '';
                             if (!$testMode) {
                                 $question->writeComment($project->databaseName(), $questionId, $answerId, $comment);
                             }
                             $deadCommentUserRefs++;
                             $message .= "Removed dead user-comment ref {$ref} from question {$questionId}, answer {$answerId}, comment {$commentId}\n";
                         }
                     }
                     $ref = $answer->userRef;
                     if (!empty($ref->id) && !in_array($ref->asString(), $userIds)) {
                         $answer->userRef->id = '';
                         if (!$testMode) {
                             $question->writeAnswer($answer);
                         }
                         $deadAnswerUserRefs++;
                         $message .= "Removed dead user-answer ref {$ref} from question {$questionId}, answer {$answerId}\n";
                     }
                 }
             }
         }
     }
     if ($deadAnswerUserRefs > 0) {
         $message .= "\n\nRemoved dead user references from {$deadAnswerUserRefs} answers\n\n";
     } else {
         $message .= "\n\nNo dead user references were found in answers\n\n";
     }
     if ($deadCommentUserRefs > 0) {
         $message .= "\n\nRemoved dead user references from {$deadCommentUserRefs} comments\n\n";
     } else {
         $message .= "\n\nNo dead user references were found in comments\n\n";
     }
     return $message;
 }