Skip to content

Commit

Permalink
Merge branch 'lf-qa' into lf-live
Browse files Browse the repository at this point in the history
* Fixes roles dropdown in user management view
* Fixes project insights DTO (now won't crash on dangling owner ref)
  • Loading branch information
rmunn committed Mar 4, 2020
2 parents 71a4795 + 2f94428 commit 254e587
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 15 deletions.
127 changes: 127 additions & 0 deletions scripts/tools/changeSiteName.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#!/usr/bin/php -q

<?php

require_once('../scriptsConfig.php');

use Api\Model\Shared\ProjectListModel;
use Api\Model\Shared\ProjectModel;
use Api\Model\Shared\UserListModel;
use Api\Model\Shared\UserModel;

(php_sapi_name() == 'cli') or die('this script must be run on the command-line');

// When we change the site name, don't update the date modified timestamps
define('MAPPERMODEL_NO_TIMESTAMP_UPDATE', true);

class ChangeSiteName
{
public static function getNewSiteName($target, $siteName) {
if (strpos($siteName, "languageforge") !== false) {
if ($target == "qa") {
return "qa.languageforge.org";
}
return "languageforge.localhost";
}
if (strpos($siteName, "scriptureforge") !== false) {
if ($target == "qa") {
return "qa.scriptureforge.org";
}
return "scriptureforge.localhost";
}
return '';
}

public static function run($mode, $target)
{
$testMode = ($mode != 'run');
$siteNameCount = array();

// loop over every project
$projectList = new ProjectListModel();
$projectList->read();

print "Parsing " . $projectList->count . " projects.\n";
foreach ($projectList->entries as $projectParams) { // foreach existing project
$projectId = $projectParams['id'];
$project = new ProjectModel($projectId);
$siteName = $project->siteName;
$newSiteName = self::getNewSiteName($target, $siteName);
if ($newSiteName) {
$project->siteName = $newSiteName;
if (!$testMode) {
$project->write();
}
if (array_key_exists($siteName, $siteNameCount)) {
$siteNameCount[$siteName]++;
} else {
$siteNameCount[$siteName] = 1;
}
}
}
foreach(array_keys($siteNameCount) as $from) {
$count = $siteNameCount[$from];
print "$count $from projects changed site to " . self::getNewSiteName($target, $from) . "\n";
}
print "\n";

$siteNameCount = array();

// loop over every user
$userList = new UserListModel();
$userList->read();
$userChangeCount = 0;
print "Parsing " . $userList->count . " users.\n";
foreach ($userList->entries as $userParams) {
$siteNamesToRemove = array();
$userId = $userParams['id'];
$user = new UserModel($userId);
foreach ($user->siteRole->getArrayCopy() as $siteName => $role) {
$newSiteName = self::getNewSiteName($target, $siteName);
if ($newSiteName) {
$user->siteRole[$newSiteName] = $role;
$siteNamesToRemove[] = $siteName;
if (array_key_exists($siteName, $siteNameCount)) {
$siteNameCount[$siteName]++;
} else {
$siteNameCount[$siteName] = 1;
}
$userChangeCount++;
}
}
foreach ($siteNamesToRemove as $siteName) {
unset($user->siteRole[$siteName]);
}
if (!$testMode) {
$user->write();
}
}
print "$userChangeCount users changed\n\n";
foreach(array_keys($siteNameCount) as $from) {
$count = $siteNameCount[$from];
print "$count users of $from projects changed site to " . self::getNewSiteName($target, $from) . "\n";
}
print "\n";
}
}
if (count($argv) != 3) {
print "Usage:\n" . "php changeSiteName.php [run|test] [qa|local]\n\n" .
"examples:\n\n" . "php changeSiteName.php test local\n - test changes but do not make actual changes. " .
"Change site names to the localhost site available on developer machines\n\n" .
"php changeSiteName.php run qa\n - change the database. change site names to the QA site\n";
exit;
}

$mode = $argv[1];
if ($mode != 'test' && $mode != 'run') {
print "Error: first argument must be either 'test' or 'run' which determines script run mode\n";
exit;
}

$target = $argv[2];
if ($target != 'qa' && $target != 'local') {
print "Error: second argument must be either 'qa' or 'local' which determines the target site\n";
exit;
}

ChangeSiteName::run($mode, $target);
13 changes: 13 additions & 0 deletions scripts/tools/csvInsights.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/php -q

<?php

require_once('../scriptsConfig.php');

use Api\Model\Shared\Dto\ProjectInsightsDto;
use Api\Library\Shared\Website;

(php_sapi_name() == 'cli') or die('this script must be run on the command-line');

ProjectInsightsDto::csvInsightsToFile(Website::get('languageforge.org'), 'languageforge.csv');
ProjectInsightsDto::csvInsightsToFile(Website::get('scriptureforge.org'), 'scriptureforge.csv');
46 changes: 35 additions & 11 deletions src/Api/Model/Shared/Dto/ProjectInsightsDto.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,17 @@ public static function singleProjectInsights($id, $website) {
$projectData->url = "/app/{$project->appName}/$project->id/";

// owner data
$owner = UserCommands::readUser($project->ownerRef->asString());
try {
$owner = UserCommands::readUser($project->ownerRef->asString());
} catch (\Exception $e) {
# there appears to be a dangling owner ref in our data
$owner = [
'username' => 'unknown',
'email' => 'unknown',
'name' => 'unknown',
'role' => 'unknown',
];
}
$projectData->ownerUserName = $owner['username'];
$projectData->ownerEmail = $owner['email'];
$projectData->ownerName = $owner['name'];
Expand Down Expand Up @@ -72,11 +82,13 @@ public static function singleProjectInsights($id, $website) {
$recentUsers = [];
$lastActivityDate = null;
foreach ($projectActivity->entries as $event) {
$userId = (string) $event['userRef'];
$users[$userId] = array_key_exists($userId, $users) ? $users[$userId] + 1 : 1;
if (date_create($event['date']) > date_create()->modify('-180 days')) {
$recentUsers[$userId] = true;
};
if (array_key_exists('userRef', $event)) {
$userId = (string) $event['userRef'];
$users[$userId] = array_key_exists($userId, $users) ? $users[$userId] + 1 : 1;
if (date_create($event['date']) > date_create()->modify('-180 days')) {
$recentUsers[$userId] = true;
};
}
$lastActivityDate = $lastActivityDate === null ? $event['date']->toDateTime() : max($event['date']->toDateTime(), $lastActivityDate);
}
$projectData->activeUsers = 0;
Expand Down Expand Up @@ -165,6 +177,22 @@ public static function allProjectInsights($website)
}

public static function csvInsights($website) {
$filePointer = fopen('php://memory', 'r+');
self::writeInsightsToCsvFilePointer($website, $filePointer);
rewind($filePointer);
$csv = stream_get_contents($filePointer);
fclose($filePointer);
return $csv;
}

public static function csvInsightsToFile($website, $filename) {
$filePointer = fopen($filename, 'w');
$count = self::writeInsightsToCsvFilePointer($website, $filePointer);
fclose($filePointer);
print "Wrote $count insights to CSV file $filename\n";
}

private static function writeInsightsToCsvFilePointer($website, $filePointer) {
$insights = ProjectInsightsDto::allProjectInsights($website);

// convert camelCase properties to sentence case for table headings
Expand All @@ -175,15 +203,11 @@ public static function csvInsights($website) {
}

// in order to get automatic escaping of CSV we have to write to a "file"
$filePointer = fopen('php://memory', 'r+');
fputcsv($filePointer, $headings);
foreach ($insights->projectList as $row) {
fputcsv($filePointer, array_values((array) $row));
}
rewind($filePointer);
$csv = stream_get_contents($filePointer);
fclose($filePointer);
return $csv;
return count($insights->projectList);
}

private static function appName($website) {
Expand Down
4 changes: 3 additions & 1 deletion src/Api/Model/Shared/Mapper/MapperModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ public function write()
{
CodeGuard::checkTypeAndThrow($this->id, 'Api\Model\Shared\Mapper\Id');
$now = UniversalTimestamp::now();
$this->dateModified = $now;
if (! defined('MAPPERMODEL_NO_TIMESTAMP_UPDATE')) {
$this->dateModified = $now;
}
if (Id::isEmpty($this->id)) {
$this->dateCreated = $now;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,15 @@ export class RoleDropdownController implements angular.IController {
if (changes.roles) this.buildRoleDetails();

if (changes.selectedRole) {
if (!this.selectedRole) this.selectedRole = this.roles[this.roles.length - 1];
this.selectedRoleDetail = this.roleDetails.find(p => p.role.key === this.selectedRole.key);
const selectedRole = changes.selectedRole.currentValue || changes.selectedRole;
const selectedRoleDetail = this.roleDetails.find(p => p.role.key === (selectedRole.key || selectedRole));
if (selectedRoleDetail) {
this.selectedRole = selectedRoleDetail.role;
this.selectedRoleDetail = selectedRoleDetail;
} else {
this.selectedRole = this.roles[this.roles.length - 1];
this.selectedRoleDetail = this.roleDetails.find(p => p.role.key === this.selectedRole.key);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

<li class="list-group-item user-summary-item" data-ng-repeat="user in $ctrl.visibleMembers">
<div>
<img src="{{$ctrl.getAvatarUrl(user.avatar_ref)}}" class="rounded-circle" id="smallAvatarURL" />
<img ng-src="{{$ctrl.getAvatarUrl(user.avatar_ref)}}" class="rounded-circle" id="smallAvatarURL" />
</div>
<div style="flex-grow: 1;" ng-class="{'text-muted': user.isInvitee}">
<span ng-if="user.name">{{user.name}}<span ng-if="$ctrl.userIsCurrentUser(user)"> (you)</span><br></span>
Expand Down

0 comments on commit 254e587

Please sign in to comment.