Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
5fa4a40
Lists the publications from Academics Analytics in a modal in the pub…
betsyecastro Sep 30, 2022
23f9482
Renders academics analytics publications in a modal through a livewir…
betsyecastro Oct 6, 2022
1f2604a
Adds pagination feature to publications listed on modal
betsyecastro Oct 7, 2022
c62eff4
Error when attempting to render collection from livewire view
betsyecastro Oct 11, 2022
1b9574c
AA: rename from academics to academic
wunc Oct 13, 2022
2e2f577
AA: working modal show event
wunc Oct 13, 2022
0f42081
AA: caches aa_publications
wunc Oct 13, 2022
6c859bb
Style: fixes indentation
wunc Oct 13, 2022
c26c27c
AA: records as new instances
wunc Oct 14, 2022
0a80a2b
AA: pub data as data-attributes
wunc Oct 14, 2022
ba0d8cd
Merging into develop
betsyecastro Oct 14, 2022
2bc50f2
Merging into local branch
betsyecastro Oct 14, 2022
69146d4
Imports publications to the editor
betsyecastro Oct 26, 2022
edbd731
Rearranges selectors with data for JS functionality and applies some …
betsyecastro Oct 31, 2022
07b5bbb
Applies a couple of additional style improvments
betsyecastro Oct 31, 2022
3047962
Adds all publications to editor
betsyecastro Nov 22, 2022
b5b0bcd
Fixes Select All button style
betsyecastro Nov 23, 2022
d80d5fa
Merge branch 'develop' of github.com:utdal/profiles into develop
betsyecastro Nov 23, 2022
62acf73
Fixes iteration over publications object when selecting all
betsyecastro Nov 28, 2022
ca43f3b
Fixes Select All button style
betsyecastro Nov 29, 2022
81e7f80
Merge branch 'develop' of github.com:utdal/profiles into develop
betsyecastro Dec 2, 2022
18cd941
Artisan command to search and add DOI to existing publications
betsyecastro Dec 16, 2022
fb8ab8c
Fixes profiles_count variable
betsyecastro Dec 16, 2022
1e99e76
Adds job for adding doi to existing publications
betsyecastro Dec 19, 2022
5c8081e
Merge branch 'develop' of github.com:utdal/profiles into develop
betsyecastro Dec 19, 2022
26d2d2e
Moves function searchPublicationByTitlonAndYear to Profile model and …
betsyecastro Jan 4, 2023
c2f81ec
Removes job for adding DOI to existing publications
betsyecastro Jan 4, 2023
2b86d10
Fixes syntax errors in app/Console/Commands/AddDoiToExistingPublicati…
betsyecastro Jan 4, 2023
c777439
Removes console message left by mistake from app/Console/Commands/Ad…
betsyecastro Jan 4, 2023
cdde980
Refactoring to improve memory usage when running add-doi artisan command
betsyecastro Jan 11, 2023
90f0b84
Corrects use of variable with cached values that exhausted the memory
betsyecastro Jan 12, 2023
697eb06
Corrects log messages
betsyecastro Jan 13, 2023
70ac208
Adds API client service provider for Orcid and AA
betsyecastro Jan 17, 2023
8b76111
API Service Providers implement api client interface
betsyecastro Jan 19, 2023
1bc4721
Includes PublicationsApi mock
betsyecastro Jan 24, 2023
fe99e74
Merge branch 'import-data-from-academic-analytics' into api-client-se…
betsyecastro Jan 24, 2023
b5a73de
Merges AA Publications feature
betsyecastro Jan 24, 2023
55a5aa4
API Publications Import
betsyecastro Feb 22, 2023
9bac516
Corrects default value for doi regex
betsyecastro Feb 22, 2023
aeb156d
Correction in parameter passed to mocked method
betsyecastro Feb 22, 2023
15b4cd9
Correction in default value of doi regex
betsyecastro Feb 22, 2023
432ad8a
Validates status code before attempting to return array response
betsyecastro Feb 23, 2023
816ca98
Adds data->academic_analytics_id to profile json object test in API test
betsyecastro Feb 23, 2023
c1fefed
Removes unnecessary AAfactory file
betsyecastro Feb 23, 2023
335bd33
Removes unnecessary OrcidApiServiceProvider file
betsyecastro Feb 23, 2023
0e17ebd
Fixes Psalm errors
betsyecastro Feb 23, 2023
567cda4
Fixes Psalm errors
betsyecastro Feb 24, 2023
a3a167a
Fixes view for the case of no publications available for import.
betsyecastro Feb 28, 2023
eaea6ca
Fixes variable type returned by getPublications method which caused a…
betsyecastro Mar 2, 2023
de1ba67
Fixes variable type returned by getPublications method
betsyecastro Mar 3, 2023
e28581a
Fixes Psalm error
betsyecastro Mar 6, 2023
ad188d5
Fixes Psalm error
betsyecastro Mar 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ TESTING_MENU=true
GOOGLE_ANALYTICS_ID=
INFLUUENT_API_KEY=
WOS_TOKEN=
ORCID_TOKEN=
ACADEMIC_ANALYTICS_KEY=

DB_CONNECTION=mysql
DB_HOST=
Expand Down
227 changes: 227 additions & 0 deletions app/Console/Commands/AddDoiToExistingPublications.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
<?php

namespace App\Console\Commands;

use App\Profile;
use App\ProfileData;
use App\Providers\AAPublicationsApiServiceProvider;
use Illuminate\Support\Facades\Log;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cache;

class AddDoiToExistingPublications extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'profiles:add-doi {starting_character : The first letter of the last name of the profiles to run command for.}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Search the DOI to add it to the existing publications for the profiles with the first letter of their last name given.';

/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$starting_character = (string)$this->argument('starting_character');

$profiles = Cache::remember(
"profiles-starting-with-{$starting_character}",
15 * 60,
fn() => $this->profilesMissingDoi($starting_character)
);

$profiles_bar = $this->output->createProgressBar(count($profiles));
$profiles_bar->setFormat('debug');
$profiles_bar->start();

$this->lineAndLog("********** {$profiles->count()} Profiles found with publications without DOI ************ \n");

foreach ($profiles as $profile) {

$profile_publications = $profile->data;

$publications_bar = $this->output->createProgressBar(count($profile->data));
$publications_bar->setFormat('debug');
$publications_bar->start();

$pubs_service_provider = App::make(AAPublicationsApiServiceProvider::class);
$aa_publications = $pubs_service_provider
->getCachedPublications($profile->id, $profile->academic_analytics_id);

$publications_found_in_url = $publications_found_in_title = $publications_found_in_aa = $doi_not_found_counter = 0;

$this->lineAndLog("********** {$profile_publications->count()} Publications found without DOI for {$profile->full_name} ************\n");

foreach ($profile_publications as $publication) {

$this->lineAndLog( "--------- {$publication->id} -----------\n");

$doi = $aa_title = null;

// Search in the URL
if (!empty($publication->url)) {
$this->lineAndLog("Searching for DOI in URL...");
$doi = $this->validateDoiRegex($publication->url);

$this->verifyAndSaveDoi($publication, $doi, 'url', $publications_found_in_url, $publications_found_in_title, $publications_found_in_aa);

}

// Search in the title
if (is_null($doi) && !empty($publication->title)) {
$this->lineAndLog("Searching for DOI in the title...");
$doi = $this->validateDoiRegex(strip_tags(html_entity_decode($publication->title)));

$this->verifyAndSaveDoi($publication, $doi, 'title', $publications_found_in_url, $publications_found_in_title, $publications_found_in_aa);

}

// Match the AA Publication
if (is_null($doi)) {
$this->lineAndLog("Searching for DOI in Academic Analytics...");

$aa_pub_found = ProfileData::searchPublicationByTitleAndYear(
$publication->title,
$publication->year,
$aa_publications ??
$pubs_service_provider->getCachedPublications($profile->id, $profile->academic_analytics_id));

$doi = $aa_pub_found[0];
$aa_title = $aa_pub_found[1];

$this->verifyAndSaveDoi($publication, $doi, 'Academic Analytics', $publications_found_in_url, $publications_found_in_title, $publications_found_in_aa, $aa_title);
}

if (is_null($doi)) { $doi_not_found_counter++; }

$publications_bar->advance();
}

$publications_bar->finish();

$this->lineAndLogResults($publications_found_in_url, $publications_found_in_title, $publications_found_in_aa, $doi_not_found_counter, $profile->full_name);

$profiles_bar->advance();

}

$profiles_bar->finish();

return Command::SUCCESS;
}

/**
* Verify given doi. If the doi is not null, updates the profile_data record and increment the counter of doi's found.
*/
public function verifyAndSaveDoi($publication, $doi, $search_field, &$publications_found_in_url, &$publications_found_in_title, &$publications_found_in_aa, $aa_title = null)
{

if (is_null($doi)) {
$this->lineAndLog("DOI not found in {$search_field}.");
}
else {

$publication->updateData(['doi' => $doi]);
if (!is_null($aa_title)) {
$publication->insertData(['aa_title' => $aa_title]);
$this->log("Title {$publication->title} found as {$aa_title} in Academic Analytics Publications\n.");
}

$publication->save();
$this->lineAndLog("DOI {$doi} FOUND IN {$search_field} and updated.");

switch ($search_field)
{
case 'title':
++$publications_found_in_title;
break;
case 'url':
++$publications_found_in_url;
break;
case 'Academic Analytics':
++$publications_found_in_aa;
break;
}

}

}

/**
* Validate DOI regex
*
* @param string $doi_expression
* @return string|null
*/
public function validateDoiRegex($doi_expression)
{
$doi_regex = config('app.doi_regex');

$doi = null;

preg_match($doi_regex, $doi_expression, $matches);

if (!empty($matches[1])) {
$doi = rtrim(trim($matches[1], "\xC2\xA0"), '.');
}

return $doi;
}

/**
* Retrieves profiles with publications that have DOI missing
*
* @param string $starting_character
* @return Collection
*/
public function profilesMissingDoi(string $starting_character)
{
return Profile::LastNameStartWithCharacter($starting_character)
->withWhereHas('data', function($q) {
$q->where('type', 'publications')
->whereNull('data->doi');
})->get();
}

/**
* Output total numbers for each profile processed to the console and log file
*/
public function lineAndLogResults($publications_found_in_url, $publications_found_in_title, $publications_found_in_aa, $doi_not_found_counter, $profile_full_name): void
{
$this->lineAndLog("TOTAL:");
if ($publications_found_in_url > 0 ) { $this->lineAndLog("{$publications_found_in_url} DOI found by url and added successfully."); }
if ($publications_found_in_title > 0 ) { $this->lineAndLog("{$publications_found_in_title} DOI found by title and added successfully."); }
if ($publications_found_in_aa > 0 ) { $this->lineAndLog("{$publications_found_in_aa} DOI found in Academic Analytics and added successfully."); }
$this->lineAndLog("{$doi_not_found_counter} PUBLICATIONS NOT FOUND.", 'error');
$this->lineAndLog("***************** End of Report for {$profile_full_name} ********************");
}

/**
* Output a message to the console and log file
*/
public function lineAndLog(string $message, string $type = 'info'): void
{
$this->line($message, $type);
Log::$type($message);
}

/**
* Output a message to the log file
*/
public function Log(string $message, string $type = 'info'): void
{
Log::$type($message);
}
}
1 change: 0 additions & 1 deletion app/Http/Controllers/ProfilesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ public function edit(Profile $profile, $section)
->route('profiles.show', $profile->slug)
->with('flash_message', 'Publications updated via ORCID.');
}

$data = $profile->data()->$section()->get();

// if no data, include one item to use as a template
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/Testing/TestingController.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public function showLoginAsList(Request $request)
*
* @param Request $request
* @param int $id
* @return \Illuminate\Http\RedirectResponse
* @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse
*/
public function loginAs(Request $request, $id)
{
Expand Down
86 changes: 86 additions & 0 deletions app/Http/Livewire/PublicationsImportModal.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

namespace App\Http\Livewire;

use App\Profile;
use App\Providers\AAPublicationsApiServiceProvider;
use Livewire\Component;
use Livewire\WithPagination;
use Illuminate\Support\Facades\App;

class PublicationsImportModal extends Component
{
use WithPagination;

protected $paginationTheme = 'bootstrap';
protected $listeners = ['AAPublicationsModalShown' => 'showModal', 'addToEditor', 'removeFromEditor', 'addAllToEditor', 'removeAllFromEditor'];
public Profile $profile;
public bool $modalVisible = false;
public bool $allChecked = false;
public $importedPublications = [];
public $perPage = 10;
public $allPublicationsCount;

public function showModal()
{
$this->modalVisible = true;
}

public function addToEditor($publicationId)
{
array_push($this->importedPublications, $publicationId);
$this->emit( 'alert', "Added to the Editor!", 'success');
}

public function removeFromEditor($publicationId)
{
if (($key = array_search($publicationId, $this->importedPublications)) !== false) {
unset($this->importedPublications[$key]);
}
$this->emit('alert', "Removed from the Editor!", 'success');
}

public function addAllToEditor()
{
$pubs_to_import = App::call([$this, 'getNewPublications'])->whereIn('imported', false);
$this->importedPublications = $pubs_to_import->pluck('id')->all();
$this->allChecked = true;
$this->emit('JSAddAllToEditor', $pubs_to_import);
}

public function removeAllFromEditor()
{
$this->reset('importedPublications');
$this->reset('allChecked');
}
/**
*
* @return \Illuminate\Database\Eloquent\Collection
*/
public function getNewPublications(AAPublicationsApiServiceProvider $pubServiceProvider)
{
$aaPublications = $pubServiceProvider->getCachedPublications($this->profile->id, $this->profile->academic_analytics_id);

return $aaPublications
->whereNotIn('doi', $this->profile->publications->pluck('data.doi')->filter()->values());
}

public function getPublicationsProperty()
{
$aaPublications = App::call([$this, 'getNewPublications']);

$this->allPublicationsCount = count($aaPublications);

$aaPublications
->each(function($elem, $key) {
$elem->imported = (in_array($elem->id, $this->importedPublications));
});

return $aaPublications->sortByDesc('sort_order')->paginate($this->perPage);
}

public function render()
{
return view('livewire.publications-import-modal');
}
}
18 changes: 18 additions & 0 deletions app/Http/Livewire/ShowModal.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace App\Http\Livewire;

use App\Profile;
use Livewire\Component;

class ShowModal extends Component
{
public bool $modalVisible = false;
public Profile $profile;
protected $listeners = ['showModal'];

public function showModal()
{
$this->emit('loadPublications');
}
}
Loading