2016-10-31 20:59:46 -07:00
< ? php
namespace App\Console\Commands ;
2021-04-14 10:17:57 -07:00
use App\Models\Department ;
2022-10-18 15:18:09 -07:00
use App\Models\Group ;
2020-11-30 17:11:44 -08:00
use Illuminate\Console\Command ;
2021-06-10 13:15:52 -07:00
use App\Models\Setting ;
2020-11-30 17:11:44 -08:00
use App\Models\Ldap ;
2021-06-10 13:15:52 -07:00
use App\Models\User ;
2016-10-31 20:59:46 -07:00
use App\Models\Location ;
2020-11-30 17:11:44 -08:00
use Log ;
2016-10-31 20:59:46 -07:00
class LdapSync extends Command
{
/**
* The name and signature of the console command .
*
* @ var string
*/
2022-06-27 19:49:59 -07:00
protected $signature = 'snipeit:ldap-sync {--location=} {--location_id=} {--base_dn=} {--filter=} {--summary} {--json_summary}' ;
2016-10-31 20:59:46 -07:00
/**
* The console command description .
*
* @ var string
*/
2020-11-30 17:11:44 -08:00
protected $description = 'Command line LDAP sync' ;
2020-08-14 14:45:05 -07:00
/**
* Create a new command instance .
2020-11-30 17:11:44 -08:00
*
* @ return void
2016-10-31 20:59:46 -07:00
*/
2020-11-30 17:11:44 -08:00
public function __construct ()
2016-10-31 20:59:46 -07:00
{
parent :: __construct ();
}
/**
* Execute the console command .
*
* @ return mixed
*/
public function handle ()
{
2023-02-01 16:36:30 -08:00
// If LDAP enabled isn't set to 1 (ldap_enabled!=1) then we should cut this short immediately without going any further
if ( Setting :: getSettings () -> ldap_enabled != '1' ) {
$this -> error ( 'LDAP is not enabled. Aborting. See Settings > LDAP to enable it.' );
}
2020-11-30 17:11:44 -08:00
ini_set ( 'max_execution_time' , env ( 'LDAP_TIME_LIM' , 600 )); //600 seconds = 10 minutes
ini_set ( 'memory_limit' , env ( 'LDAP_MEM_LIM' , '500M' ));
$ldap_result_username = Setting :: getSettings () -> ldap_username_field ;
$ldap_result_last_name = Setting :: getSettings () -> ldap_lname_field ;
$ldap_result_first_name = Setting :: getSettings () -> ldap_fname_field ;
2022-08-10 12:55:30 -07:00
$ldap_result_active_flag = Setting :: getSettings () -> ldap_active_flag ;
2020-11-30 17:11:44 -08:00
$ldap_result_emp_num = Setting :: getSettings () -> ldap_emp_num ;
$ldap_result_email = Setting :: getSettings () -> ldap_email ;
2021-04-05 19:26:04 -07:00
$ldap_result_phone = Setting :: getSettings () -> ldap_phone_field ;
$ldap_result_jobtitle = Setting :: getSettings () -> ldap_jobtitle ;
2021-06-10 13:15:52 -07:00
$ldap_result_country = Setting :: getSettings () -> ldap_country ;
2021-04-14 10:17:57 -07:00
$ldap_result_dept = Setting :: getSettings () -> ldap_dept ;
2022-03-24 11:24:39 -07:00
$ldap_result_manager = Setting :: getSettings () -> ldap_manager ;
2022-09-12 11:40:16 -07:00
$ldap_default_group = Setting :: getSettings () -> ldap_default_group ;
2020-08-14 14:45:05 -07:00
2020-11-30 17:11:44 -08:00
try {
$ldapconn = Ldap :: connectToLdap ();
Ldap :: bindAdminToLdap ( $ldapconn );
} catch ( \Exception $e ) {
if ( $this -> option ( 'json_summary' )) {
2021-06-10 13:15:52 -07:00
$json_summary = [ 'error' => true , 'error_message' => $e -> getMessage (), 'summary' => []];
2020-11-30 17:11:44 -08:00
$this -> info ( json_encode ( $json_summary ));
}
LOG :: info ( $e );
2021-06-10 13:15:52 -07:00
2020-11-30 17:11:44 -08:00
return [];
2016-10-31 20:59:46 -07:00
}
2021-06-10 13:15:52 -07:00
$summary = [];
2016-10-31 20:59:46 -07:00
2020-11-30 17:11:44 -08:00
try {
if ( $this -> option ( 'base_dn' ) != '' ) {
$search_base = $this -> option ( 'base_dn' );
LOG :: debug ( 'Importing users from specified base DN: \"' . $search_base . '\".' );
2020-10-21 15:13:36 -07:00
} else {
2020-11-30 17:11:44 -08:00
$search_base = null ;
}
2022-06-27 19:49:59 -07:00
if ( $this -> option ( 'filter' ) != '' ) {
$results = Ldap :: findLdapUsers ( $search_base , - 1 , $this -> option ( 'filter' ));
} else {
$results = Ldap :: findLdapUsers ( $search_base );
}
2020-11-30 17:11:44 -08:00
} catch ( \Exception $e ) {
if ( $this -> option ( 'json_summary' )) {
2021-06-10 13:15:52 -07:00
$json_summary = [ 'error' => true , 'error_message' => $e -> getMessage (), 'summary' => []];
2020-11-30 17:11:44 -08:00
$this -> info ( json_encode ( $json_summary ));
2017-12-14 12:57:43 -08:00
}
2020-11-30 17:11:44 -08:00
LOG :: info ( $e );
2021-06-10 13:15:52 -07:00
2020-11-30 17:11:44 -08:00
return [];
2017-12-14 12:57:43 -08:00
}
2017-01-11 23:37:14 -08:00
2020-11-30 17:11:44 -08:00
/* Determine which location to assign users to by default. */
2021-11-19 16:38:46 -08:00
$location = null ; // TODO - this would be better called "$default_location", which is more explicit about its purpose
2020-11-30 17:11:44 -08:00
2021-06-10 13:15:52 -07:00
if ( $this -> option ( 'location' ) != '' ) {
2020-11-30 17:11:44 -08:00
$location = Location :: where ( 'name' , '=' , $this -> option ( 'location' )) -> first ();
LOG :: debug ( 'Location name ' . $this -> option ( 'location' ) . ' passed' );
LOG :: debug ( 'Importing to ' . $location -> name . ' (' . $location -> id . ')' );
2021-06-10 13:15:52 -07:00
} elseif ( $this -> option ( 'location_id' ) != '' ) {
2020-11-30 17:11:44 -08:00
$location = Location :: where ( 'id' , '=' , $this -> option ( 'location_id' )) -> first ();
LOG :: debug ( 'Location ID ' . $this -> option ( 'location_id' ) . ' passed' );
LOG :: debug ( 'Importing to ' . $location -> name . ' (' . $location -> id . ')' );
2020-10-21 15:13:36 -07:00
}
2018-02-13 17:06:42 -08:00
2021-06-10 13:15:52 -07:00
if ( ! isset ( $location )) {
2020-11-30 17:11:44 -08:00
LOG :: debug ( 'That location is invalid or a location was not provided, so no location will be assigned by default.' );
2016-10-31 20:59:46 -07:00
}
2020-11-30 17:11:44 -08:00
/* Process locations with explicitly defined OUs, if doing a full import. */
2022-06-27 19:49:59 -07:00
if ( $this -> option ( 'base_dn' ) == '' && $this -> option ( 'filter' ) == '' ) {
2020-11-30 17:11:44 -08:00
// Retrieve locations with a mapped OU, and sort them from the shallowest to deepest OU (see #3993)
$ldap_ou_locations = Location :: where ( 'ldap_ou' , '!=' , '' ) -> get () -> toArray ();
2021-06-10 13:15:52 -07:00
$ldap_ou_lengths = [];
2020-11-30 17:11:44 -08:00
2020-12-01 21:26:52 -08:00
foreach ( $ldap_ou_locations as $ou_loc ) {
2021-06-10 13:15:52 -07:00
$ldap_ou_lengths [] = strlen ( $ou_loc [ 'ldap_ou' ]);
2017-01-11 23:37:14 -08:00
}
2020-11-30 17:11:44 -08:00
array_multisort ( $ldap_ou_lengths , SORT_ASC , $ldap_ou_locations );
2018-01-23 18:15:36 -08:00
2021-06-10 13:15:52 -07:00
if ( count ( $ldap_ou_locations ) > 0 ) {
2020-11-30 17:11:44 -08:00
LOG :: debug ( 'Some locations have special OUs set. Locations will be automatically set for users in those OUs.' );
2017-01-11 23:37:14 -08:00
}
2020-11-30 17:11:44 -08:00
// Inject location information fields
2021-06-10 13:15:52 -07:00
for ( $i = 0 ; $i < $results [ 'count' ]; $i ++ ) {
$results [ $i ][ 'ldap_location_override' ] = false ;
$results [ $i ][ 'location_id' ] = 0 ;
2018-01-23 18:15:36 -08:00
}
2016-10-31 20:59:46 -07:00
2020-11-30 17:11:44 -08:00
// Grab subsets based on location-specific DNs, and overwrite location for these users.
foreach ( $ldap_ou_locations as $ldap_loc ) {
try {
2021-06-10 13:15:52 -07:00
$location_users = Ldap :: findLdapUsers ( $ldap_loc [ 'ldap_ou' ]);
2021-11-10 11:37:10 -08:00
} catch ( \Exception $e ) { // TODO: this is stolen from line 77 or so above
2020-11-30 17:11:44 -08:00
if ( $this -> option ( 'json_summary' )) {
2021-06-10 13:15:52 -07:00
$json_summary = [ 'error' => true , 'error_message' => trans ( 'admin/users/message.error.ldap_could_not_search' ) . ' Location: ' . $ldap_loc [ 'name' ] . ' (ID: ' . $ldap_loc [ 'id' ] . ') cannot connect to "' . $ldap_loc [ 'ldap_ou' ] . '" - ' . $e -> getMessage (), 'summary' => []];
2020-11-30 17:11:44 -08:00
$this -> info ( json_encode ( $json_summary ));
}
LOG :: info ( $e );
2021-06-10 13:15:52 -07:00
2020-11-30 17:11:44 -08:00
return [];
2016-10-31 20:59:46 -07:00
}
2021-06-10 13:15:52 -07:00
$usernames = [];
for ( $i = 0 ; $i < $location_users [ 'count' ]; $i ++ ) {
2020-11-30 17:11:44 -08:00
if ( array_key_exists ( $ldap_result_username , $location_users [ $i ])) {
2021-06-10 13:15:52 -07:00
$location_users [ $i ][ 'ldap_location_override' ] = true ;
$location_users [ $i ][ 'location_id' ] = $ldap_loc [ 'id' ];
2020-11-30 17:11:44 -08:00
$usernames [] = $location_users [ $i ][ $ldap_result_username ][ 0 ];
}
}
// Delete located users from the general group.
foreach ( $results as $key => $generic_entry ) {
2021-06-10 13:15:52 -07:00
if (( is_array ( $generic_entry )) && ( array_key_exists ( $ldap_result_username , $generic_entry ))) {
2020-11-30 17:11:44 -08:00
if ( in_array ( $generic_entry [ $ldap_result_username ][ 0 ], $usernames )) {
unset ( $results [ $key ]);
}
}
2016-10-31 20:59:46 -07:00
}
2020-11-30 17:11:44 -08:00
$global_count = $results [ 'count' ];
$results = array_merge ( $location_users , $results );
$results [ 'count' ] = $global_count ;
2016-10-31 20:59:46 -07:00
}
2020-08-14 14:45:05 -07:00
}
2020-11-30 17:11:44 -08:00
/* Create user account entries in Snipe-IT */
2021-06-10 13:15:52 -07:00
$tmp_pass = substr ( str_shuffle ( '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' ), 0 , 20 );
2020-11-30 17:11:44 -08:00
$pass = bcrypt ( $tmp_pass );
2022-10-20 16:52:40 -07:00
$manager_cache = [];
2023-01-09 15:23:19 -08:00
if ( $ldap_default_group != null ) {
$default = Group :: find ( $ldap_default_group );
if ( ! $default ) {
$ldap_default_group = null ; // un-set the default group if that group doesn't exist
}
}
2021-06-10 13:15:52 -07:00
for ( $i = 0 ; $i < $results [ 'count' ]; $i ++ ) {
$item = [];
$item [ 'username' ] = isset ( $results [ $i ][ $ldap_result_username ][ 0 ]) ? $results [ $i ][ $ldap_result_username ][ 0 ] : '' ;
$item [ 'employee_number' ] = isset ( $results [ $i ][ $ldap_result_emp_num ][ 0 ]) ? $results [ $i ][ $ldap_result_emp_num ][ 0 ] : '' ;
$item [ 'lastname' ] = isset ( $results [ $i ][ $ldap_result_last_name ][ 0 ]) ? $results [ $i ][ $ldap_result_last_name ][ 0 ] : '' ;
$item [ 'firstname' ] = isset ( $results [ $i ][ $ldap_result_first_name ][ 0 ]) ? $results [ $i ][ $ldap_result_first_name ][ 0 ] : '' ;
$item [ 'email' ] = isset ( $results [ $i ][ $ldap_result_email ][ 0 ]) ? $results [ $i ][ $ldap_result_email ][ 0 ] : '' ;
$item [ 'ldap_location_override' ] = isset ( $results [ $i ][ 'ldap_location_override' ]) ? $results [ $i ][ 'ldap_location_override' ] : '' ;
$item [ 'location_id' ] = isset ( $results [ $i ][ 'location_id' ]) ? $results [ $i ][ 'location_id' ] : '' ;
$item [ 'telephone' ] = isset ( $results [ $i ][ $ldap_result_phone ][ 0 ]) ? $results [ $i ][ $ldap_result_phone ][ 0 ] : '' ;
$item [ 'jobtitle' ] = isset ( $results [ $i ][ $ldap_result_jobtitle ][ 0 ]) ? $results [ $i ][ $ldap_result_jobtitle ][ 0 ] : '' ;
$item [ 'country' ] = isset ( $results [ $i ][ $ldap_result_country ][ 0 ]) ? $results [ $i ][ $ldap_result_country ][ 0 ] : '' ;
$item [ 'department' ] = isset ( $results [ $i ][ $ldap_result_dept ][ 0 ]) ? $results [ $i ][ $ldap_result_dept ][ 0 ] : '' ;
2022-03-24 11:24:39 -07:00
$item [ 'manager' ] = isset ( $results [ $i ][ $ldap_result_manager ][ 0 ]) ? $results [ $i ][ $ldap_result_manager ][ 0 ] : '' ;
2021-04-14 10:17:57 -07:00
2022-09-12 11:40:16 -07:00
2021-04-14 10:17:57 -07:00
$department = Department :: firstOrCreate ([
2021-06-10 13:15:52 -07:00
'name' => $item [ 'department' ],
2021-04-14 10:17:57 -07:00
]);
2021-06-10 13:15:52 -07:00
$user = User :: where ( 'username' , $item [ 'username' ]) -> first ();
2020-11-30 17:11:44 -08:00
if ( $user ) {
// Updating an existing user.
2021-06-10 13:15:52 -07:00
$item [ 'createorupdate' ] = 'updated' ;
2020-11-30 17:11:44 -08:00
} else {
// Creating a new user.
$user = new User ;
$user -> password = $pass ;
2022-08-10 12:55:30 -07:00
$user -> activated = 1 ; // newly created users can log in by default, unless AD's UAC is in use, or an active flag is set (below)
2021-06-10 13:15:52 -07:00
$item [ 'createorupdate' ] = 'created' ;
2020-11-30 17:11:44 -08:00
}
2021-06-10 13:15:52 -07:00
$user -> first_name = $item [ 'firstname' ];
$user -> last_name = $item [ 'lastname' ];
$user -> username = $item [ 'username' ];
$user -> email = $item [ 'email' ];
$user -> employee_num = e ( $item [ 'employee_number' ]);
$user -> phone = $item [ 'telephone' ];
$user -> jobtitle = $item [ 'jobtitle' ];
$user -> country = $item [ 'country' ];
2021-04-14 10:17:57 -07:00
$user -> department_id = $department -> id ;
2020-11-30 17:11:44 -08:00
2022-05-15 09:25:28 -07:00
if ( $item [ 'manager' ] != null ) {
2022-10-20 16:52:40 -07:00
// Check Cache first
if ( isset ( $manager_cache [ $item [ 'manager' ]])) {
// found in cache; use that and avoid extra lookups
$user -> manager_id = $manager_cache [ $item [ 'manager' ]];
} else {
// Get the LDAP Manager
try {
$ldap_manager = Ldap :: findLdapUsers ( $item [ 'manager' ], - 1 , $this -> option ( 'filter' ));
} catch ( \Exception $e ) {
2022-10-21 17:43:53 -07:00
\Log :: warning ( " Manager lookup caused an exception: " . $e -> getMessage () . " . Falling back to direct username lookup " );
2022-10-20 16:52:40 -07:00
// Hail-mary for Okta manager 'shortnames' - will only work if
// Okta configuration is using full email-address-style usernames
$ldap_manager = [
" count " => 1 ,
0 => [
$ldap_result_username => [ $item [ 'manager' ]]
]
];
}
2022-10-19 18:36:16 -07:00
2022-10-20 16:52:40 -07:00
if ( $ldap_manager [ " count " ] > 0 ) {
2022-08-19 09:09:03 -07:00
2022-10-20 16:52:40 -07:00
// Get the Manager's username
// PHP LDAP returns every LDAP attribute as an array, and 90% of the time it's an array of just one item. But, hey, it's an array.
$ldapManagerUsername = $ldap_manager [ 0 ][ $ldap_result_username ][ 0 ];
2022-08-19 09:09:03 -07:00
2022-10-20 16:52:40 -07:00
// Get User from Manager username.
$ldap_manager = User :: where ( 'username' , $ldapManagerUsername ) -> first ();
2022-08-19 09:09:03 -07:00
2022-10-20 16:52:40 -07:00
if ( $ldap_manager && isset ( $ldap_manager -> id )) {
// Link user to manager id.
$user -> manager_id = $ldap_manager -> id ;
}
2022-08-19 09:09:03 -07:00
}
2022-10-20 16:52:40 -07:00
$manager_cache [ $item [ 'manager' ]] = $ldap_manager && isset ( $ldap_manager -> id ) ? $ldap_manager -> id : null ; // Store results in cache, even if 'failed'
2022-05-15 09:25:28 -07:00
}
2022-03-24 11:24:39 -07:00
}
2022-10-19 19:01:52 -07:00
2020-11-30 17:11:44 -08:00
// Sync activated state for Active Directory.
2022-08-10 12:55:30 -07:00
if ( ! empty ( $ldap_result_active_flag )) { // IF we have an 'active' flag set....
// ....then *most* things that are truthy will activate the user. Anything falsey will deactivate them.
// (Specifically, we don't handle a value of '0.0' correctly)
$raw_value = @ $results [ $i ][ $ldap_result_active_flag ][ 0 ];
$filter_var = filter_var ( $raw_value , FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE );
$boolean_cast = ( bool ) $raw_value ;
$user -> activated = $filter_var ? ? $boolean_cast ; // if filter_var() was true or false, use that. If it's null, use the $boolean_cast
} elseif ( array_key_exists ( 'useraccountcontrol' , $results [ $i ]) ) {
// ....otherwise, (ie if no 'active' LDAP flag is defined), IF the UAC setting exists,
// ....then use the UAC setting on the account to determine can-log-in vs. cannot-log-in
/* The following is _probably_ the correct logic , but we can ' t use it because
2020-11-30 17:11:44 -08:00
some users may have been dependent upon the previous behavior , and this
could cause additional access to be available to users they don ' t want
to allow to log in .
$useraccountcontrol = $results [ $i ][ 'useraccountcontrol' ][ 0 ];
if (
// based on MS docs at: https://support.microsoft.com/en-us/help/305144/how-to-use-useraccountcontrol-to-manipulate-user-account-properties
( $useraccountcontrol & 0x200 ) && // is a NORMAL_ACCOUNT
! ( $useraccountcontrol & 0x02 ) && // *and* _not_ ACCOUNTDISABLE
! ( $useraccountcontrol & 0x10 ) // *and* _not_ LOCKOUT
) {
$user -> activated = 1 ;
} else {
$user -> activated = 0 ;
} */
2021-06-10 13:15:52 -07:00
$enabled_accounts = [
2023-01-31 16:49:41 -08:00
'512' , // 0x200 NORMAL_ACCOUNT
'544' , // 0x220 NORMAL_ACCOUNT, PASSWD_NOTREQD
'66048' , // 0x10200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD
'66080' , // 0x10220 NORMAL_ACCOUNT, PASSWD_NOTREQD, DONT_EXPIRE_PASSWORD
'262656' , // 0x40200 NORMAL_ACCOUNT, SMARTCARD_REQUIRED
'262688' , // 0x40220 NORMAL_ACCOUNT, PASSWD_NOTREQD, SMARTCARD_REQUIRED
'328192' , // 0x50200 NORMAL_ACCOUNT, SMARTCARD_REQUIRED, DONT_EXPIRE_PASSWORD
'328224' , // 0x50220 NORMAL_ACCOUNT, PASSWD_NOT_REQD, SMARTCARD_REQUIRED, DONT_EXPIRE_PASSWORD
'4194816' , // 0x400200 NORMAL_ACCOUNT, DONT_REQ_PREAUTH
2021-06-10 13:15:52 -07:00
'4260352' , // 0x410200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD, DONT_REQ_PREAUTH
'1049088' , // 0x100200 NORMAL_ACCOUNT, NOT_DELEGATED
2023-01-31 16:49:41 -08:00
'1114624' , // 0x110200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD, NOT_DELEGATED,
2020-11-30 17:11:44 -08:00
];
2021-06-10 13:15:52 -07:00
$user -> activated = ( in_array ( $results [ $i ][ 'useraccountcontrol' ][ 0 ], $enabled_accounts )) ? 1 : 0 ;
2020-11-30 17:11:44 -08:00
// If we're not using AD, and there isn't an activated flag set, activate all users
2022-08-10 12:55:30 -07:00
} /* implied 'else' here - leave the $user -> activated flag alone . Newly - created accounts will be active .
already - existing accounts will be however the administrator has set them */
2020-11-30 17:11:44 -08:00
if ( $item [ 'ldap_location_override' ] == true ) {
$user -> location_id = $item [ 'location_id' ];
2021-06-10 13:15:52 -07:00
} elseif (( isset ( $location )) && ( ! empty ( $location ))) {
2020-11-30 17:11:44 -08:00
if (( is_array ( $location )) && ( array_key_exists ( 'id' , $location ))) {
$user -> location_id = $location [ 'id' ];
} elseif ( is_object ( $location )) {
$user -> location_id = $location -> id ;
}
}
$user -> ldap_import = 1 ;
$errors = '' ;
if ( $user -> save ()) {
2021-06-10 13:15:52 -07:00
$item [ 'note' ] = $item [ 'createorupdate' ];
$item [ 'status' ] = 'success' ;
2023-01-09 15:23:19 -08:00
if ( $item [ 'createorupdate' ] === 'created' && $ldap_default_group ) {
$user -> groups () -> attach ( $ldap_default_group );
}
2022-09-13 11:40:10 -07:00
2020-11-30 17:11:44 -08:00
} else {
foreach ( $user -> getErrors () -> getMessages () as $key => $err ) {
$errors .= $err [ 0 ];
}
2021-06-10 13:15:52 -07:00
$item [ 'note' ] = $errors ;
$item [ 'status' ] = 'error' ;
2020-11-30 17:11:44 -08:00
}
array_push ( $summary , $item );
2016-10-31 20:59:46 -07:00
}
2020-11-30 17:11:44 -08:00
if ( $this -> option ( 'summary' )) {
for ( $x = 0 ; $x < count ( $summary ); $x ++ ) {
2021-06-10 13:15:52 -07:00
if ( $summary [ $x ][ 'status' ] == 'error' ) {
2020-11-30 17:11:44 -08:00
$this -> error ( 'ERROR: ' . $summary [ $x ][ 'firstname' ] . ' ' . $summary [ $x ][ 'lastname' ] . ' (username: ' . $summary [ $x ][ 'username' ] . ') was not imported: ' . $summary [ $x ][ 'note' ]);
} else {
$this -> info ( 'User ' . $summary [ $x ][ 'firstname' ] . ' ' . $summary [ $x ][ 'lastname' ] . ' (username: ' . $summary [ $x ][ 'username' ] . ') was ' . strtoupper ( $summary [ $x ][ 'createorupdate' ]) . '.' );
}
}
2021-06-10 13:15:52 -07:00
} elseif ( $this -> option ( 'json_summary' )) {
$json_summary = [ 'error' => false , 'error_message' => '' , 'summary' => $summary ]; // hardcoding the error to false and the error_message to blank seems a bit weird
2017-10-06 16:15:14 -07:00
$this -> info ( json_encode ( $json_summary ));
2020-11-30 17:11:44 -08:00
} else {
return $summary ;
2016-10-31 20:59:46 -07:00
}
}
}