foldershare-8.x-1.2/foldershare.drush.inc
foldershare.drush.inc
<?php /** * @file * Implements drush commands specific to the module. */ use Drupal\Core\Cache\Cache; use Drupal\user\Entity\User; use Drupal\foldershare\Settings; use Drupal\foldershare\Entity\FolderShare; use Drupal\foldershare\ManageUsageStatistics; use Drupal\foldershare\Entity\FolderShareScheduledTask; /** * Implements hook_drush_command(). */ function foldershare_drush_command() { $commands [ 'foldershare' ] = [ 'description' => 'List FolderShare module commands.' , 'aliases' => [ 'fs' , ], 'options' => [ 'all' => [ 'description' => 'List all commands, including those for debugging.' , 'hidden' => TRUE, ], ], 'bootstrap' => DRUSH_BOOTSTRAP_NONE, 'category' => 'San Diego Supercomputer Center (SDSC)' , 'topic' => TRUE, 'examples' => [ 'drush foldershare' => 'List FolderShare commands' , ], ]; $commands [ 'foldershare-admin' ] = [ 'description' => 'Perform administrative functions.' , 'hidden' => TRUE, 'aliases' => [ 'fsadmin' , ], 'arguments' => [ 'uid' => [ 'description' => 'The user ID owning affected content' , ], 'newuid' => [ 'description' => 'The user ID for a new owner of the content' , ], ], 'options' => [ 'deleteall' => [ 'description' => 'Delete all content' , ], 'deleteby' => [ 'description' => 'Delete all content owned by a user' , ], 'changeownerby' => [ 'description' => 'Change ownership of all content owned by a user' , ], 'unsharewith' => [ 'description' => 'Remove the user from all sharing grants' , ], ], 'examples' => [ 'drush foldershare-admin --deleteall' => 'Delete everything' , 'drush foldershare-admin --deleteby 123' => 'Delete all owned by 123' , 'drush foldershare-admin --changeownerby 123 456' => 'Change ownership of all owned by 123 to be 456' , 'drush foldershare-admin --unsharewith 123' => 'Remove sharing with 123' , ], 'drupal dependencies' => [ 'foldershare' , ], 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL, 'category' => 'San Diego Supercomputer Center (SDSC)' , ]; $commands [ 'foldershare-disabled' ] = [ 'description' => 'List, enable, and disable items marked as "disabled".' , 'hidden' => TRUE, 'aliases' => [ 'fsdisable' , 'fsdisabled' , ], 'arguments' => [ 'id' => [ 'description' => 'The entity ID to disable or enable' , ], ], 'options' => [ 'disable' => [ 'description' => 'Disable the item' , ], 'enable' => [ 'description' => 'Enable an item' , ], 'enableall' => [ 'description' => 'Enable all disabled items' , ], 'list' => [ 'description' => 'List all disabled items' , ], ], 'examples' => [ 'drush foldershare-disabled' => 'List disabled items' , 'drush foldershare-disabled --list' => 'List disabled items' , 'drush foldershare-disabled --disable ID' => 'Disable item with entity ID' , 'drush foldershare-disabled --enable ID' => 'Enable item with entity ID' , 'drush foldershare-disabled --enableall' => 'Enable all items' , ], 'drupal dependencies' => [ 'foldershare' , ], 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL, 'category' => 'San Diego Supercomputer Center (SDSC)' , ]; $commands [ 'foldershare-fsck' ] = [ 'description' => 'Find and fix file system problems.' , 'aliases' => [ 'fsfsck' , ], 'options' => [ 'fix' => [ 'description' => 'Automatically fix problems' , ], ], 'examples' => [ 'drush foldershare-fsck' => 'Find file system problems' , 'drush foldershare-fsck --fix' => 'Find and fix file system problems' , ], 'drupal dependencies' => [ 'foldershare' , ], 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL, 'category' => 'San Diego Supercomputer Center (SDSC)' , ]; $commands [ 'foldershare-hidden' ] = [ 'description' => 'List, hide, or show items marked as "hidden".' , 'hidden' => TRUE, 'aliases' => [ 'fshide' , 'fshidden' , ], 'arguments' => [ 'id' => [ 'description' => 'The entity ID to hide or show' , ], ], 'options' => [ 'hide' => [ 'description' => 'Hide an item' , ], 'list' => [ 'description' => 'List all hidden items' , ], 'show' => [ 'description' => 'show an item' , ], 'showall' => [ 'description' => 'show all hidden items' , ], ], 'examples' => [ 'drush foldershare-hidden' => 'List hidden items' , 'drush foldershare-hidden --list' => 'List hidden items' , 'drush foldershare-hidden --hide ID' => 'Hide item with entity ID' , 'drush foldershare-hidden --show ID' => 'Show item with entity ID' , 'drush foldershare-hidden --showall' => 'Show all items' , ], 'drupal dependencies' => [ 'foldershare' , ], 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL, 'category' => 'San Diego Supercomputer Center (SDSC)' , ]; $commands [ 'foldershare-lock' ] = [ 'description' => 'List, acquire, or release locks.' , 'hidden' => TRUE, 'aliases' => [ 'foldershare-locks' , 'fslock' , 'fslocks' , ], 'arguments' => [ 'id' => [ 'description' => "The root entity ID to lock or unlock" , ], ], 'options' => [ 'list' => [ 'description' => 'List root folder locks' , ], 'lock' => [ 'description' => 'Lock the root folder of an item' , ], 'unlock' => [ 'description' => 'Unlock the root folder of an item' , ], 'unlockall' => [ 'description' => 'Unlock all root folders' , ], ], 'examples' => [ 'drush foldershare-lock' => 'List locked root items' , 'drush foldershare-lock --list' => 'List locked root items' , 'drush foldershare-lock --lock ID' => 'Lock root item with entity ID' , 'drush foldershare-lock --unlock ID' => 'Unlock root item with entity ID' , 'drush foldershare-lock --unlockall' => 'Unlock all root items' , ], 'drupal dependencies' => [ 'foldershare' , ], 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL, 'category' => 'San Diego Supercomputer Center (SDSC)' , ]; $commands [ 'foldershare-config' ] = [ 'description' => 'List module config.' , 'aliases' => [ 'fsconfig' , ], 'examples' => [ 'drush foldershare-config' => 'List configuration' , ], 'drupal dependencies' => [ 'foldershare' , ], 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL, 'category' => 'San Diego Supercomputer Center (SDSC)' , ]; $commands [ 'foldershare-tasks' ] = [ 'description' => 'List, run, and delete module tasks.' , 'hidden' => TRUE, 'aliases' => [ 'fstasks' , ], 'options' => [ 'list' => [ 'description' => 'List scheduled tasks' , ], 'delete' => [ 'description' => 'Delete a task by its ID' , ], 'deleteall' => [ 'description' => 'Delete all tasks' , ], 'run' => [ 'description' => 'Run tasks that are ready' , ], ], 'arguments' => [ 'id' => [ 'description' => "The ID of a task" , ], ], 'examples' => [ 'drush foldershare-tasks' => 'List scheduled tasks' , 'drush foldershare-tasks --list' => 'List scheduled tasks' , 'drush foldershare-tasks --run' => 'Run ready scheduled tasks' , ], 'drupal dependencies' => [ 'foldershare' , ], 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL, 'category' => 'San Diego Supercomputer Center (SDSC)' , ]; $commands [ 'foldershare-usage' ] = [ 'description' => 'List module usage by user.' , 'aliases' => [ 'fsusage' , ], 'options' => [ 'list' => [ 'description' => 'List usage per user' , ], 'update' => [ 'description' => 'Update the usage table' , ], ], 'examples' => [ 'drush foldershare-usage' => 'List usage per user' , 'drush foldershare-usage --list' => 'List usage per user' , 'drush foldershare-usage --update' => 'Update the usage table' , ], 'drupal dependencies' => [ 'foldershare' , ], 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL, 'category' => 'San Diego Supercomputer Center (SDSC)' , ]; $commands [ 'foldershare-version' ] = [ 'description' => 'Show module version number.' , 'aliases' => [ 'fsversion' , ], 'examples' => [ 'drush foldershare-version' => 'Show version number' , ], 'drupal dependencies' => [ 'foldershare' , ], 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL, 'category' => 'San Diego Supercomputer Center (SDSC)' , ]; $commands [ 'foldershare-benchmark' ] = [ 'description' => 'Benchmark selected module features.' , 'hidden' => TRUE, 'aliases' => [ 'fsbench' , 'fsbenchmark' , ], 'options' => [ 'folder' => [ 'description' => 'Benchmark folder create and delete' , ], 'lock' => [ 'description' => 'Benchmark process lock and release' , ], 'config' => [ 'description' => 'Benchmark get and set of configuration' , ], 'system' => [ 'description' => 'Benchmark misc system calls' , ], ], 'drupal dependencies' => [ 'foldershare' , ], 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL, 'category' => 'San Diego Supercomputer Center (SDSC)' , ]; return $commands ; } /*--------------------------------------------------------------------- * * Help. * *---------------------------------------------------------------------*/ /** * Lists available commands. */ function drush_foldershare() { FolderShareScheduledTask::setTaskExecutionEnabled(FALSE); $showAll = ( empty (drush_get_option( 'all' )) === FALSE); drush_print( dt( 'FolderShare: Commands for the module:' )); drush_print(sprintf( " %-22s %s" , "foldershare" , dt( "List these commands." ))); if ( $showAll === TRUE) { drush_print(sprintf( " %-22s %s" , "foldershare-admin" , dt( "Perform administrative operations." ))); } if ( $showAll === TRUE) { drush_print(sprintf( " %-22s %s" , "foldershare-benchmark" , dt( "Benchmark selected module features." ))); } if ( $showAll === TRUE) { drush_print(sprintf( " %-22s %s" , "foldershare-disabled" , dt( 'List, enable, and disable items marked as "disabled".' ))); } drush_print(sprintf( " %-22s %s" , "foldershare-fsck" , dt( "Find and fix filesystem problems." ))); if ( $showAll === TRUE) { drush_print(sprintf( " %-22s %s" , "foldershare-hidden" , dt( 'List, enable, and disable items marked as "hidden".' ))); } if ( $showAll === TRUE) { drush_print(sprintf( " %-22s %s" , "foldershare-locks" , dt( 'List, aquire, and release locks.' ))); } drush_print(sprintf( " %-22s %s" , "foldershare-config" , dt( "List module configuration." ))); if ( $showAll === TRUE) { drush_print(sprintf( " %-22s %s" , "foldershare-tasks" , dt( 'List, run, and delete module tasks.' ))); } drush_print(sprintf( " %-22s %s" , "foldershare-usage" , dt( "List module usage by user." ))); drush_print(sprintf( " %-22s %s" , "foldershare-version" , dt( "Show module version number." ))); } /*--------------------------------------------------------------------- * * Admin - delete and change owner. * *---------------------------------------------------------------------*/ /** * Performs administrative operations. * * --changeownerby Changes ownership of all content owned by a user. * --deleteall Deletes all content. * --deleteby Deletes all content owned by a user. * --unsharewith Remove the user from all sharing grants. * * @param int $uid * (optional, default = (-1)) The user entity ID of the affected user. * @param int $newuid * (optional, default = (-1)) The user entity ID of the new owner of * content, for changeownerall. */ function drush_foldershare_admin( $uid = (-1), $newuid = (-1)) { FolderShareScheduledTask::setTaskExecutionEnabled(FALSE); if ( empty (drush_get_option( 'deleteall' )) === FALSE && empty (drush_get_option( 'deleteby' )) === FALSE && empty (drush_get_option( 'unsharewith' )) === FALSE && empty (drush_get_option( 'changeownerby' )) === FALSE) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( " Too many FolderShare admin options. Only one allowed." )); drush_print(dt( ' Type "drush help foldershare-admin" for admin options.' )); return ; } if ( empty (drush_get_option( 'deleteall' )) === FALSE) { drush_foldershare_admin_deleteall( $uid , $newuid ); return ; } if ( empty (drush_get_option( 'deleteby' )) === FALSE) { drush_foldershare_admin_deleteby( $uid , $newuid ); return ; } if ( empty (drush_get_option( 'changeownerby' )) === FALSE) { drush_foldershare_admin_changeownerby( $uid , $newuid ); return ; } if ( empty (drush_get_option( 'unsharewith' )) === FALSE) { drush_foldershare_admin_unsharewith( $uid , $newuid ); return ; } drush_print(dt( "FolderShare: Error" )); drush_print(dt( " Missing or unrecognized admin option." )); drush_print(dt( ' Type "drush help foldershare-admin" for admin options.' )); } /** * Performs an administrative "delete all". * * @param int $uid * Should always be -1. * @param int $newuid * Should always be -1. */ function drush_foldershare_admin_deleteall( $uid , $newuid ) { // // Validate. // --------- // There should be no user IDs. if ( $uid !== (-1) || $newuid !== (-1)) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( " The --deleteall option does not require a user ID, but one was provided." )); drush_print(dt( " Did you mean to use --deleteby?" )); drush_print(dt( ' Type "drush help foldershare-admin" for admin options.' )); return ; } // // Explain. // -------- // Explain what will happen and to how much content. drush_print(dt( "FolderShare: Delete all" )); drush_print( '------------------------------------------------------------------------' ); drush_print(dt( "All FolderShare files and folders will be deleted immediately!" )); drush_print( "" ); drush_print(dt( "Checking the number of items to delete..." )); $nFiles = FolderShare::countNumberOfFiles(FolderShare::ANY_USER_ID); $nFolders = FolderShare::countNumberOfFolders(FolderShare::ANY_USER_ID); if (( $nFiles + $nFolders ) === 0) { drush_print(dt( "... none! There are no files or folders to delete." )); return ; } drush_print(dt( "... @nFiles files and @nFolders folders." , [ '@nFiles' => $nFiles , '@nFolders' => $nFolders , ])); drush_print( "" ); // Prompt. $answer = readline(dt( "Are you sure [y|n]? " )); if ( $answer [0] !== 'y' ) { drush_print(dt( "Aborted." )); return ; } // Execute. drush_print( "" ); drush_print(dt( "Deleting all content." )); drush_print(dt( "This may take a few minutes..." )); FolderShare::deleteAll(FolderShare::ANY_USER_ID); drush_print(dt( "Done." )); } /** * Performs an administrative "delete by". * * @param int $uid * A valid user ID. * @param int $newuid * Should always be -1. */ function drush_foldershare_admin_deleteby( $uid , $newuid ) { // Validate that there is a UID. if ( $uid < 0) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( ' The --deleteby option requires a user ID.' )); drush_print(dt( ' Type "drush help foldershare-admin" for admin options.' )); return ; } $uidEntity = User::load( $uid ); if ( $uidEntity === NULL) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( " The ID @uid does not match any known user." , [ '@uid' => $uid , ])); return ; } // Validate that there is no second UID. if ( $newuid !== (-1)) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( " The --deleteby option does not require a second user ID, but one was provided." )); drush_print(dt( ' Type "drush help foldershare-admin" for admin options.' )); return ; } // Explain. drush_print(dt( "FolderShare: Delete all items owned by @uidName (@uid)" , [ '@uid' => $uid , '@uidName' => $uidEntity ->getDisplayName(), ])); drush_print( '------------------------------------------------------------------------' ); drush_print(dt( "All FolderShare files and folders owned by the user will be deleted." )); drush_print(dt( "immediately." )); drush_print( "" ); drush_print(dt( "This can delete content owned by other users! When a folder is" )); drush_print(dt( "deleted, everything inside it is deleted too, even if it is owned by" )); drush_print(dt( "another user." )); drush_print( "" ); drush_print(dt( "This can delete content inside folders owned by other users! Files" )); drush_print(dt( "and folders owned by the user but in another user's folders will be" )); drush_print(dt( "deleted too." )); drush_print( "" ); drush_print(dt( "Checking the number of items to delete..." )); // Validate that there is content. $nFiles = FolderShare::countNumberOfFiles( $uid ); $nFolders = FolderShare::countNumberOfFolders( $uid ); if (( $nFiles + $nFolders ) === 0) { drush_print(dt( "... none! The user has no files or folders to delete." )); return ; } drush_print(dt( "... @nFiles files and @nFolders folders." , [ '@nFiles' => $nFiles , '@nFolders' => $nFolders , ])); drush_print( "" ); // Prompt. $answer = readline(dt( "Are you sure [y|n]? " )); if ( $answer [0] !== 'y' ) { drush_print(dt( "Aborted." )); return ; } // Execute. drush_print( "" ); drush_print(dt( "Deleting all content owned by @uidName (@uid)." , [ '@uid' => $uid , '@uidName' => $uidEntity ->getDisplayName(), ])); drush_print(dt( "This may take a few minutes..." )); FolderShare::deleteAll( $uid ); drush_print(dt( "Done." )); } /** * Performs an administrative "change owner by". * * @param int $uid * A valid user ID for the owner of content. * @param int $newuid * A valid user ID for the new owner of the content. */ function drush_foldershare_admin_changeownerby( $uid , $newuid ) { // Validate that there are two user IDs. if ( $uid < 0) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( ' The --changeownerall option requires a source user ID.' )); drush_print(dt( ' Type "drush help foldershare-admin" for admin options.' )); return ; } if ( $newuid < 0) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( ' The --changeownerall option requires a destination user ID.' )); drush_print(dt( ' Type "drush help foldershare-admin" for admin options.' )); return ; } $uidEntity = User::load( $uid ); if ( $uidEntity === NULL) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( " The ID @uid does not match any known user." , [ '@uid' => $uid , ])); return ; } $newuidEntity = User::load( $newuid ); if ( $newuidEntity === NULL) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( " The ID @newuid does not match any known user." , [ '@newuid' => $newuid , ])); return ; } // Explain. drush_print( "" ); drush_print(dt( "FolderShare: Change all items owned by @uidName (@uid)" , [ '@uid' => $uid , '@uidName' => $uidEntity ->getDisplayName(), ])); drush_print(dt( " to be owned by @newuidName (@newuid)" , [ '@newuid' => $newuid , '@newuidName' => $newuidEntity ->getDisplayName(), ])); drush_print( '------------------------------------------------------------------------' ); drush_print(dt( "All FolderShare files and folders owned by the first user will be" )); drush_print(dt( "changed immediately to be owned by the second user." )); drush_print( "" ); drush_print(dt( "Checking the number of items to change..." )); // Validate that there is content. $nFiles = FolderShare::countNumberOfFiles( $uid ); $nFolders = FolderShare::countNumberOfFolders( $uid ); if (( $nFiles + $nFolders ) === 0) { drush_print(dt( "... none! The user has no files or folders to change." )); return ; } drush_print(dt( "... @nFiles files and @nFolders folders." , [ '@nFiles' => $nFiles , '@nFolders' => $nFolders , ])); drush_print( "" ); // Prompt. $answer = readline(dt( "Are you sure [y|n]? " )); if ( $answer [0] !== 'y' ) { drush_print(dt( "Aborted." )); return ; } // Execute. drush_print( "" ); drush_print(dt( "Changing all content owned by @uidName (@uid() to be owned by @newuidName (@newuid)." , [ '@uid' => $uid , '@uidName' => $uidEntity ->getDisplayName(), '@newuid' => $newuid , '@newuidName' => $newuidEntity ->getDisplayName(), ])); drush_print(dt( "This may take a few minutes..." )); drush_print( "" ); FolderShare::changeAllOwnerIdByUser( $uid , $newuid ); drush_print(dt( "Done." )); } /** * Performs an administrative "unshare with". * * @param int $uid * A valid user ID for the owner of content. */ function drush_foldershare_admin_unsharewith( $uid ) { // Validate that there are two user IDs. if ( $uid < 0) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( ' The --unsharewith option requires a user ID.' )); drush_print(dt( ' Type "drush help foldershare-admin" for admin options.' )); return ; } $uidEntity = User::load( $uid ); if ( $uidEntity === NULL) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( " The ID @uid does not match any known user." , [ '@uid' => $uid , ])); return ; } // Explain. drush_print(dt( "FolderShare: Remove @uidName (@uid) from all sharing grants" , [ '@uid' => $uid , '@uidName' => $uidEntity ->getDisplayName(), ])); drush_print( '------------------------------------------------------------------------' ); drush_print(dt( "The user will be removed from all items owned by others that grant the" )); drush_print(dt( "user shared access." )); drush_print( "" ); // Prompt. $answer = readline(dt( "Are you sure [y|n]? " )); if ( $answer [0] !== 'y' ) { drush_print(dt( "Aborted." )); return ; } // Execute. drush_print( "" ); drush_print(dt( "Unsharing @uidName (@uid) from all shared content." , [ '@uid' => $uid , '@uidName' => $uidEntity ->getDisplayName(), ])); drush_print(dt( "This may take a few minutes..." )); drush_print( "" ); FolderShare::unshareFromAll( $uid ); drush_print(dt( "Done." )); } /*--------------------------------------------------------------------- * * Fix - disabled flags. * *---------------------------------------------------------------------*/ /** * Performs operations to list, enable, and disable items. * * --enable Enable an item. * --enableall Enable all items. * --disable Disable an item. * --list (default) List all hidden items. * * @param int $id * (optional, default = (-1)) The FolderShare entity ID to enable or * disable. The $id is ignored if the 'list' option is used, and * required for the 'enable' and 'disable' options. */ function drush_foldershare_disabled( $id = (-1)) { FolderShareScheduledTask::setTaskExecutionEnabled(FALSE); if ( empty (drush_get_option( 'enableall' )) === FALSE) { drush_foldershare_disabled_enableall(); return ; } if ( empty (drush_get_option( 'enable' )) === FALSE) { drush_foldershare_disabled_enable( $id ); return ; } if ( empty (drush_get_option( 'disable' )) === FALSE) { drush_foldershare_disabled_disable( $id ); return ; } // Default to a list. drush_foldershare_disabled_list(); } /** * Performs a disabled item list. */ function drush_foldershare_disabled_list() { // Table heading. drush_print(dt( 'FolderShare: Disabled files and folders' )); drush_print(sprintf( "%-20s %10s %s" , 'Owner' , 'Entity ID' , 'Path' )); drush_print(sprintf( "%-20s %10s %s" , '--------------------' , '----------' , '---------------------------------------------' )); // Get a list of everything that is disabled. Typically this is a // very short list, but it might not be. $disabledIds = FolderShare::findAllDisabledIds(); if ( count ( $disabledIds ) === 0) { drush_print(dt( "None." )); return ; } // List each item. foreach ( $disabledIds as $id ) { $item = FolderShare::load( $id ); if ( $item === NULL) { // The item does not exist. continue ; } $ownerId = $item ->getOwnerId(); $path = $item ->getPath(); if ( $item ->isFolder() === TRUE) { $path .= '/' ; } $u = User::load( $ownerId ); if ( $u === NULL) { $ownerName = sprintf( '%s (%d)' , dt( 'unknown' ), $ownerId ); } else { $ownerName = sprintf( '%s (%d)' , $u ->getDisplayName(), $ownerId ); } drush_print(sprintf( "%-20s %10d %s" , $ownerName , $id , $path )); } } /** * Performs an enable on all disabled items. */ function drush_foldershare_disabled_enableall() { // Explain. drush_print(dt( "FolderShare: Enable all disabled items" )); drush_print( '------------------------------------------------------------------------' ); drush_print(dt( "WARNING: Items marked disabled are being used by operations such as a" )); drush_print(dt( "copy or move. The mark also is used by copy operations to keep track" )); drush_print(dt( "of their progress. Manually enabling all disabled items will cause" )); drush_print(dt( "them to become available for new operations and corrupt marks used" )); drush_print(dt( "for copy operations already in progress. This can cause operations" )); drush_print(dt( "to collide and make copy operations end prematurely." )); drush_print( "" ); drush_print(dt( " ** This can corrupt the file system **" )); drush_print( "" ); drush_print(dt( "Enabling all items manually should only be done during debugging." )); drush_print( "" ); // Prompt. $answer = readline(dt( "Are you sure [y|n]? " )); if ( $answer [0] !== 'y' ) { drush_print(dt( "Aborted." )); return ; } // Execute. drush_print( "" ); drush_print(dt( "Enabling all disabled items." )); drush_print(dt( " This may take a few minutes..." )); $nChanged = FolderShare::clearAllSystemDisabled(); // Flush the entity cache so that it is not out of date compared to // the now-marked entities in the database. \Drupal::entityTypeManager()->getStorage(FolderShare::ENTITY_TYPE_ID) ->resetCache(NULL); \Drupal::service( 'cache.render' )->invalidateAll(); if ( $nChanged === 0) { drush_print(dt( "Done. No items were changed." )); } else { drush_print(dt( "Done. @count items were changed." , [ '@count' => $nChanged , ])); } } /** * Performs an enable on a specified item. * * @param int $id * The FolderShare entity ID to enable. */ function drush_foldershare_disabled_enable( $id = (-1)) { // Validate entity ID. $id = (int) $id ; if ( $id < 0) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( ' Missing entity ID to enable.' )); return ; } $item = FolderShare::load( $id ); if ( $item === NULL) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( " The entity ID @id does not match any known content." , [ '@id' => $id , ])); return ; } $path = $item ->getPath(); if ( $item ->isFolder() === TRUE) { $path .= '/' ; } // Explain. drush_print(dt( "FolderShare: Enable item ID @id at @path" , [ '@id' => $id , '@path' => $path , ])); drush_print( '------------------------------------------------------------------------' ); drush_print(dt( "WARNING: Items marked disabled are being used by operations such as a" )); drush_print(dt( "copy or move. The mark also is used by copy operations to keep track" )); drush_print(dt( "of their progress. Manually enabling a disabled item will cause it" )); drush_print(dt( "to become available for new operations that can collide if a prior" )); drush_print(dt( "operation is still in progres. This also can cause copy operations" )); drush_print(dt( "to end prematurely and leave some content uncopied. The premature end" )); drush_print(dt( "will not alert the user that the copied item is invalid." )); drush_print( "" ); drush_print(dt( " ** This can corrupt the file system **" )); drush_print( "" ); drush_print(dt( "Enabling an item manually should only be done during debugging." )); drush_print( "" ); // Prompt. $answer = readline(dt( "Are you sure [y|n]? " )); if ( $answer [0] !== 'y' ) { drush_print(dt( "Aborted." )); return ; } // Execute. drush_print( "" ); drush_print(dt( "Enabling ID @id at @path..." , [ '@id' => $id , '@path' => $path , ])); $item ->setSystemDisabled(FALSE); $item ->save(); drush_print(dt( "Done. One item was changed." )); } /** * Performs a disable on a specified item. * * @param int $id * The FolderShare entity ID to disable. */ function drush_foldershare_disabled_disable( $id = (-1)) { // Validate entity ID. $id = (int) $id ; if ( $id < 0) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( ' Missing entity ID to disable.' )); return ; } $item = FolderShare::load( $id ); if ( $item === NULL) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( " The entity ID @id does not match any known content." , [ '@id' => $id , ])); return ; } $path = $item ->getPath(); if ( $item ->isFolder() === TRUE) { $path .= '/' ; } // Explain. drush_print(dt( "FolderShare: Disable item ID @id at @path" , [ '@id' => $id , '@path' => $path , ])); drush_print( '------------------------------------------------------------------------' ); drush_print(dt( "WARNING: Disabling an item will prevent users, including administrators," )); drush_print(dt( "from starting new operations using it. This includes viewing," )); drush_print(dt( "downloading, moving, copying, and deleting. The item will remain" )); drush_print(dt( "visible in lists and show a spinner. Normally the spinner goes away" )); drush_print(dt( "when an operation enables the item after it completes. But with a" )); drush_print(dt( "manually disabled item, there is no associated operation to enable" )); drush_print(dt( "item again. The item will remain disabled and the spinner will run" )); drush_print(dt( "indefinitely. This is like to cause user confusion." )); drush_print( "" ); drush_print(dt( "Disabling an item manually should only be done during debugging." )); drush_print( "" ); // Prompt. $answer = readline(dt( "Are you sure [y|n]? " )); if ( $answer [0] !== 'y' ) { drush_print(dt( "Aborted." )); return ; } // Execute. drush_print( "" ); drush_print(dt( "Disabling ID @id at @path..." , [ '@id' => $id , '@path' => $path , ])); $item ->setSystemDisabled(TRUE); $item ->save(); drush_print(dt( "Done. One item was changed." )); } /*--------------------------------------------------------------------- * * Fix - hidden flags. * *---------------------------------------------------------------------*/ /** * Performs operations to list, show, and hide items. * * --hide Hide a non-hidden item. * --list (default) List all hidden items. * --show Show a hidden item. * --showall Show all hidden items. * * @param int $id * (optional, default = (-1)) The FolderShare entity ID to show or * hide. The $id is ignored if the 'list' option is used, and * required for the 'show' and 'hide' options. */ function drush_foldershare_hidden( $id = (-1)) { FolderShareScheduledTask::setTaskExecutionEnabled(FALSE); if ( empty (drush_get_option( 'showall' )) === FALSE) { drush_foldershare_hidden_showall(); return ; } if ( empty (drush_get_option( 'show' )) === FALSE) { drush_foldershare_hidden_show( $id ); return ; } if ( empty (drush_get_option( 'hide' )) === FALSE) { drush_foldershare_hidden_hide( $id ); return ; } // Default to a list. drush_foldershare_hidden_list(); } /** * Performs a hidden item list. */ function drush_foldershare_hidden_list() { // Table heading. drush_print(dt( 'FolderShare: Hidden files and folders' )); drush_print(sprintf( "%-20s %10s %s" , dt( 'Owner' ), dt( 'Entity ID' ), dt( 'Path' ))); drush_print(sprintf( "%-20s %10s %s" , '--------------------' , '----------' , '---------------------------------------------' )); // Get a list of everything that is hidden. Typically this is a // very short list, but it might not be. $hiddenIds = FolderShare::findAllHiddenIds(); if ( count ( $hiddenIds ) === 0) { drush_print(dt( "None." )); return ; } // List each item. foreach ( $hiddenIds as $id ) { $item = FolderShare::load( $id ); if ( $item === NULL) { // The item does not exist. continue ; } $ownerId = $item ->getOwnerId(); $path = $item ->getPath(); if ( $item ->isFolder() === TRUE) { $path .= '/' ; } $u = User::load( $ownerId ); if ( $u === NULL) { $ownerName = sprintf( '%s (%d)' , dt( 'unknown' ), $ownerId ); } else { $ownerName = sprintf( '%s (%d)' , $u ->getDisplayName(), $ownerId ); } drush_print(sprintf( "%-20s %10d %s" , $ownerName , $id , $path )); } } /** * Performs a show on all hidden items. */ function drush_foldershare_hidden_showall() { // Explain. drush_print(dt( "FolderShare: Show all items" )); drush_print( '------------------------------------------------------------------------' ); drush_print(dt( "WARNING: Items marked hidden are in the process of being deleted." )); drush_print(dt( "Manually marking all hidden items as visible will let users see the" )); drush_print(dt( "items as they are being deleted, but it will not abort the delete." )); drush_print(dt( "This can be confusing to users and it can cause problems if a user" )); drush_print(dt( "tries to use an item just as it is being deleted." )); drush_print( "" ); drush_print(dt( "Showing hidden items should only be done during debugging." )); drush_print( "" ); // Prompt. $answer = readline(dt( "Are you sure [y|n]? " )); if ( $answer [0] !== 'y' ) { drush_print(dt( "Aborted." )); return ; } // Execute. drush_print( "" ); drush_print(dt( "Showing all hidden items." )); drush_print(dt( " This may take a few minutes..." )); $nChanged = FolderShare::clearAllSystemHidden(); // Flush the entity cache so that it is not out of date compared to // the now-marked entities in the database. \Drupal::entityTypeManager()->getStorage(FolderShare::ENTITY_TYPE_ID) ->resetCache(NULL); \Drupal::service( 'cache.render' )->invalidateAll(); if ( $nChanged === 0) { drush_print(dt( "Done. No items were changed." )); } else { drush_print(dt( "Done. @count items were changed." , [ '@count' => $nChanged , ])); } } /** * Performs a show on a selected item. * * @param int $id * A valid FolderShare entity ID. */ function drush_foldershare_hidden_show( $id ) { // Validate entity ID. $id = (int) $id ; if ( $id < 0) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( ' Missing entity ID to show.' )); return ; } $item = FolderShare::load( $id ); if ( $item === NULL) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( " The entity ID @id does not match any known content." , [ '@id' => $id , ])); return ; } $path = $item ->getPath(); if ( $item ->isFolder() === TRUE) { $path .= '/' ; } drush_print(dt( "FolderShare: Show item ID @id at @path" , [ '@id' => $id , '@path' => $path , ])); drush_print( '------------------------------------------------------------------------' ); drush_print(dt( "WARNING: Items marked hidden are in the process of being deleted." )); drush_print(dt( "Manually marking a hidden item as visible will let users see the item" )); drush_print(dt( "before it is deleted, but it will not abort the delete. This can be" )); drush_print(dt( "confusing to users and it can cause problems if a user tries to use an" )); drush_print(dt( "item just as it is being deleted." )); drush_print( "" ); drush_print(dt( "Showing hidden items should only be done during debugging." )); drush_print( "" ); // Prompt. $answer = readline(dt( "Are you sure [y|n]? " )); if ( $answer [0] !== 'y' ) { drush_print(dt( "Aborted." )); return ; } // Execute. drush_print( "" ); drush_print(dt( 'Showing ID @id at @path...' , [ '@id' => $id , '@path' => $path , ])); $item ->setSystemHidden(FALSE); $item ->save(); // Flush the entity cache so that it is not out of date compared to // the now-marked entities in the database. \Drupal::entityTypeManager()->getStorage(FolderShare::ENTITY_TYPE_ID) ->resetCache(NULL); \Drupal::service( 'cache.render' )->invalidateAll(); drush_print(dt( "Done. One item was changed." )); } /** * Performs a hide on a selected item. * * @param int $id * A valid FolderShare entity ID. */ function drush_foldershare_hidden_hide( $id ) { // Validate entity ID. $id = (int) $id ; if ( $id < 0) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( ' Missing entity ID to hide.' )); return ; } $item = FolderShare::load( $id ); if ( $item === NULL) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( " The entity ID @id does not match any known content." , [ '@id' => $id , ])); return ; } $path = $item ->getPath(); if ( $item ->isFolder() === TRUE) { $path .= '/' ; } // Explain. drush_print(dt( "FolderShare: Hide item ID @id at @path" , [ '@id' => $id , '@path' => $path , ])); drush_print( '------------------------------------------------------------------------' ); drush_print(dt( "WARNING: Items marked hidden are in the process of being deleted." )); drush_print(dt( "Manually marking an item hidden will make it invisible to users, but" )); drush_print(dt( "will not delete it." )); drush_print( "" ); drush_print(dt( "Hiding items should only be done during debugging." )); drush_print( "" ); // Prompt. $answer = readline(dt( "Are you sure [y|n]? " )); if ( $answer [0] !== 'y' ) { drush_print(dt( "Aborted." )); return ; } // Execute. drush_print( "" ); drush_print(dt( 'Hiding ID @id at @path...' , [ '@id' => $id , '@path' => $path , ])); $item ->setSystemHidden(TRUE); $item ->save(); // Flush the entity cache so that it is not out of date compared to // the now-marked entities in the database. \Drupal::entityTypeManager()->getStorage(FolderShare::ENTITY_TYPE_ID) ->resetCache(NULL); \Drupal::service( 'cache.render' )->invalidateAll(); drush_print(dt( "Done. One item was changed." )); } /*--------------------------------------------------------------------- * * Fix - root locks. * *---------------------------------------------------------------------*/ /** * Performs operations to list, lock, and unlock exclusive access locks. * * --list (default) List all root locks. * --lock Lock a root. * --unlock Unlock a root. */ function drush_foldershare_lock( $id = (-1)) { FolderShareScheduledTask::setTaskExecutionEnabled(FALSE); if ( empty (drush_get_option( 'lock' )) === FALSE) { drush_foldershare_lock_lock( $id ); return ; } if ( empty (drush_get_option( 'unlock' )) === FALSE) { drush_foldershare_lock_unlock( $id ); return ; } // Default to a list. drush_foldershare_lock_list(); } /** * Performs a lock list. */ function drush_foldershare_lock_list() { // Table heading. drush_print(dt( 'FolderShare: Locked root items' )); drush_print(sprintf( "%-20s %10s %s" , dt( 'Owner' ), dt( 'Root ID' ), dt( 'Path' ))); drush_print(sprintf( "%-20s %10s %s" , '--------------------' , '----------' , '---------------------------------------------' )); // Get a list of everything that is disabled. Typically this is a // very short list, but it might not be. $rootIds = FolderShare::findAllRootItemIds(); $lockedRootIds = []; foreach ( $rootIds as $rootId ) { if (FolderShare::isRootOperationLockAvailable( $rootId ) === FALSE) { $lockedRootIds [] = $rootId ; } } if ( count ( $lockedRootIds ) === 0) { drush_print(dt( "None." )); return ; } // List each item. foreach ( $lockedRootIds as $rootId ) { $item = FolderShare::load( $rootId ); if ( $item === NULL) { // The item does not exist. continue ; } $ownerId = $item ->getOwnerId(); $path = $item ->getPath(); if ( $item ->isFolder() === TRUE) { $path .= '/' ; } $u = User::load( $ownerId ); if ( $u === NULL) { $ownerName = sprintf( '%s (%d)' , dt( 'unknown' ), $ownerId ); } else { $ownerName = sprintf( '%s (%d)' , $u ->getDisplayName(), $ownerId ); } drush_print(sprintf( "%-20s %10d %s" , $ownerName , $rootId , $path )); } } /** * Performs a lock on a selected item. * * @param int $id * The FolderShare entity ID to lock. */ function drush_foldershare_lock_lock( $id ) { // Validate entity ID. $id = (int) $id ; if ( $id < 0) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( ' Missing entity ID to lock.' )); return ; } $item = FolderShare::load( $id ); if ( $item === NULL) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( " The entity ID @id does not match any known content." , [ '@id' => $id , ])); return ; } if ( $item ->isRootItem() === FALSE) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( ' The entity ID @id is not a root item and therefore cannot be locked.' , [ '@id' => $id , ])); return ; } $path = $item ->getPath(); if ( $item ->isFolder() === TRUE) { $path .= '/' ; } // Explain. drush_print(dt( "FolderShare: Lock root ID @id at @path" , [ '@id' => $id , '@path' => $path , ])); drush_print( '------------------------------------------------------------------------' ); drush_print(dt( "WARNING: Locking a root item will block all further operations on the" )); drush_print(dt( "entire folder tree under the root. Create, copy, delete, move, and" )); drush_print(dt( "other operations will fail for all users, including administrators." )); drush_print( "" ); drush_print(dt( "Locking manually should only be done during debugging." )); drush_print( "" ); // Prompt. $answer = readline(dt( "Are you sure [y|n]? " )); if ( $answer [0] !== 'y' ) { drush_print(dt( "Aborted." )); return ; } // Execute. drush_print( "" ); drush_print(dt( "Locking root ID @id @path..." , [ '@id' => $id , '@path' => $path , ])); FolderShare::acquireRootOperationLock( $id ); drush_print(dt( "Done. One lock was changed." )); } /** * Performs an unlock on a selected item. * * @param int $id * The FolderShare entity ID to unlock. */ function drush_foldershare_lock_unlock( $id ) { // Validate entity ID. $id = (int) $id ; if ( $id < 0) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( ' Missing entity ID to unlock.' )); return ; } $item = FolderShare::load( $id ); if ( $item === NULL) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( " The entity ID @id does not match any known content." , [ '@id' => $id , ])); return ; } if ( $item ->isRootItem() === FALSE) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( ' The entity ID @id is not a root item and therefore cannot be unlocked.' , [ '@id' => $id , ])); return ; } $path = $item ->getPath(); if ( $item ->isFolder() === TRUE) { $path .= '/' ; } // Explain. drush_print(dt( "FolderShare: Unlock root ID @id at @path" , [ '@id' => $id , '@path' => $path , ])); drush_print(dt( "Unlock item" )); drush_print( '------------------------------------------------------------------------' ); drush_print(dt( "WARNING: Unlocking a root item will allow new operations to be started" )); drush_print(dt( "anywhere within the folder tree under the root. If there is a pending" )); drush_print(dt( "operations on anything in the folder tree, a new operation can collide" )); drush_print(dt( "by attempting to change the same files and folders." )); drush_print( "" ); drush_print(dt( " ** This can corrupt the file system **" )); drush_print( "" ); drush_print(dt( "Unlocking manually should only be done during debugging." )); drush_print( "" ); // Prompt. $answer = readline(dt( "Are you sure [y|n]? " )); if ( $answer [0] !== 'y' ) { drush_print(dt( "Aborted." )); return ; } // Unlock the item. drush_print( "" ); drush_print(dt( "Unlocking root ID @id @path..." , [ '@id' => $id , '@path' => $path , ])); FolderShare::releaseRootOperationLock( $id ); drush_print(dt( "Done. One lock was changed." )); } /*--------------------------------------------------------------------- * * Fix - file system check. * *---------------------------------------------------------------------*/ /** * Checks the file system. * * --fix Run file system checks. */ function drush_foldershare_fsck() { FolderShareScheduledTask::setTaskExecutionEnabled(FALSE); $fix = ( empty (drush_get_option( 'fix' )) === FALSE); // Scan and possibly fix the file system. if ( $fix === TRUE) { drush_print(dt( "FolderShare: File system check and repair" )); drush_print( '------------------------------------------------------------------------' ); drush_print(dt( "This may take a few minutes..." )); drush_print( "" ); $originalMode = \Drupal::state()->get( 'system.maintenance_mode' ); if ( $originalMode !== 1) { drush_print(dt( 'Entering maintenance mode.' )); \Drupal::state()->set( 'system.maintenance_mode' , 1); drush_print( "" ); } $wereFixed = FolderShare::fsck(TRUE); if ( $originalMode !== 1) { drush_print(dt( 'Exiting maintenance mode.' )); \Drupal::state()->set( 'system.maintenance_mode' , $originalMode ); drush_print( "" ); } if ( $wereFixed === TRUE) { drush_print(dt( 'Repairs were made.' )); } else { drush_print(dt( 'No repairs were needed or made.' )); } } else { drush_print(dt( 'FolderShare: File system check only' )); drush_print( '------------------------------------------------------------------------' ); drush_print(dt( 'This may take a few minutes...' )); drush_print( "" ); $needToBeFixed = FolderShare::fsck(FALSE); if ( $needToBeFixed === TRUE) { drush_print(dt( 'Repairs need to be made.' )); drush_print(dt( 'To make repairs, run "drush foldershare-fsck --fix".' )); } else { drush_print(dt( 'No repairs are needed.' )); } } } /*--------------------------------------------------------------------- * * Module configuration - configuration. * *---------------------------------------------------------------------*/ /** * Lists module configuration. * * The module's configuration is listed, including that of plugins. */ function drush_foldershare_config() { FolderShareScheduledTask::setTaskExecutionEnabled(FALSE); $moduleHandler = \Drupal::moduleHandler(); $typeManager = \Drupal::entityTypeManager(); drush_print(dt( "FolderShare configuration" )); drush_print( '------------------------------------------------------------------------' ); // // Files. drush_print(dt( "Files:" )); drush_print( '--------------------------------' ); drush_print(sprintf( "%-45s %s" , dt( 'File system:' ), Settings::getFileScheme())); drush_print(sprintf( "%-45s %s" , dt( 'New ZIP archive name:' ), Settings::getNewZipArchiveName())); drush_print(sprintf( "%-45s %s" , dt( 'New ZIP archive comment:' ), Settings::getNewZipArchiveComment())); drush_print(sprintf( "%-45s %s" , dt( 'ZIP unarchive to subfolder:' ), (Settings::getZipUnarchiveMultipleToSubfolder() === TRUE) ? 'true' : 'false' )); drush_print(sprintf( "%-45s %s" , dt( 'File name extensions restricted:' ), (Settings::getFileRestrictExtensions() === TRUE) ? 'true' : 'false' )); drush_print(sprintf( "%-45s\n%s" , dt( 'Allowed file name extensions (if restricted):' ), Settings::getAllowedNameExtensions())); drush_print( "" ); // // Interface. drush_print(dt( 'User interface:' )); drush_print( '--------------------------------' ); drush_print(sprintf( "%-45s %s" , dt( 'Command menu restricted:' ), (Settings::getCommandMenuRestrict() === TRUE) ? 'true' : 'false' )); drush_print(sprintf( "%-45s\n%s" , dt( 'Allowed commands (if restricted):' ), implode( ', ' , Settings::getCommandMenuAllowed()))); drush_print(sprintf( "%-45s %s" , dt( 'Commands report normal completion:' ), (Settings::getCommandNormalCompletionReportEnable() === TRUE) ? 'true' : 'false' )); drush_print(sprintf( "%-45s %d sec" , dt( 'Interface refresh polling interval:' ), Settings::getStatusPollingInterval())); drush_print( "" ); // // Search. drush_print(dt( 'Search:' )); drush_print( '--------------------------------' ); if ( $moduleHandler ->moduleExists( 'search' ) === FALSE) { drush_print(dt( 'Drupal core "search" module is not installed.' )); } else { try { $searchPage = $typeManager ->getStorage( 'search_page' ) ->load( 'foldershare_search' ); $searchPlugin = $searchPage ->getPlugin(); drush_print(sprintf( "%-45s %s" , dt( 'Include file text in search index:' ), ( $searchPlugin ->getSearchFileContent() === TRUE) ? 'true' : 'false' )); drush_print(sprintf( "%-45s %d bytes" , dt( 'Maximum file content to index for search:' ), $searchPlugin ->getSearchFileSize())); drush_print(sprintf( "%-45s %s" , dt( 'File types to include in search index:' ), $searchPlugin ->getSearchFileExtensions())); } catch (\Exception $e ) { // Ignore. } } drush_print( "" ); // // System. drush_print(dt( 'System:' )); drush_print( '--------------------------------' ); drush_print(sprintf( "%-45s %s" , dt( 'Activity logging:' ), (Settings::getActivityLogEnable() === TRUE) ? 'true' : 'false' )); drush_print(sprintf( "%-45s %s" , dt( 'Usage update interval:' ), Settings::getUsageUpdateInterval())); $t = ManageUsageStatistics::getLastUpdateTime(); if ( $t !== 'never' ) { if ( $t [0] === '@' ) { $t = date ( 'Y-m-d H:i:s' , intval ( substr ( $t , 1))); } else { $t = date ( 'Y-m-d H:i:s' , intval ( $t )); } } drush_print(sprintf( "%-45s %s" , dt( 'Usage last updated:' ), $t )); drush_print(sprintf( "%-45s %d sec" , dt( 'Content lock duration:' ), Settings::getContentLockDuration())); drush_print(sprintf( "%-45s %d sec" , dt( 'Operation lock duration:' ), Settings::getOperationLockDuration())); drush_print(sprintf( "%-45s %d sec" , dt( 'Task initial scheduling delay:' ), Settings::getScheduledTaskInitialDelay())); drush_print(sprintf( "%-45s %d sec" , dt( 'Task continuation scheduling delay:' ), Settings::getScheduledTaskContinuationDelay())); drush_print(sprintf( "%-45s %d sec" , dt( 'Task safety-net scheduling delay:' ), Settings::getScheduledTaskSafetyNetDelay())); drush_print(sprintf( "%-45s %4.1f %%" , dt( 'Memory use limit as % of PHP limit:' ), 100.0 * Settings::getMemoryUseLimitPercentage())); drush_print(sprintf( "%-45s %4.1f %%" , dt( 'Execution time limit as % of PHP limit:' ), 100.0 * Settings::getExecutionTimeLimitPercentage())); drush_print( "" ); // // Web services. // // REST services are provided by a separately installed FolderShare REST // module, however the services are associated with FolderShare entities. // If those services are installed, list them. drush_print(dt( 'Web services:' )); drush_print( '--------------------------------' ); if (\Drupal::moduleHandler()->moduleExists( 'rest' ) === FALSE) { drush_print(dt( 'Drupal core "rest" module not installed.' )); } else { try { $restPlugin = $typeManager ->getStorage( 'rest_resource_config' ) ->load( 'entity.foldershare' ); if ( $restPlugin !== NULL) { foreach ( $restPlugin ->getMethods() as $method ) { $formats = $restPlugin ->getFormats( $method ); $auths = $restPlugin ->getAuthenticationPRoviders( $method ); drush_print( $method ); drush_print(sprintf( " %-43s %s" , dt( "Serialization formats:" ), implode( ', ' , $formats ))); drush_print(sprintf( " %-43s %s" , dt( "Authentication providers:" ), implode( ', ' , $auths ))); } } } catch (\Exception $e ) { // Ignore. } } drush_print( "" ); // // PHP directives. drush_print(dt( 'Relevant PHP directives:' )); drush_print( '--------------------------------' ); drush_print(sprintf( "%-45s %s" , dt( 'Max upload file size (upload_max_filesize):' ), ini_get ( 'upload_max_filesize' ))); drush_print(sprintf( "%-45s %d" , dt( 'Max # of uploaded files (max_file_uploads):' ), ini_get ( 'max_file_uploads' ))); $t = ini_get ( 'post_max_size' ); if ( $t === "0" ) { drush_print(sprintf( "%-45s %s" , dt( 'Max post message size (post_max_size):' ), dt( '(unlimited)' ))); } else { drush_print(sprintf( "%-45s %s" , dt( 'Max post message size (post_max_size):' ), $t )); } $t = (int) ini_get ( 'max_input_time' ); if ( $t === (-1)) { drush_print(sprintf( "%-45s %s" , dt( 'Max post processing time (max_input_time):' ), dt( '(uses max_execution_time)' ))); } else { drush_print(sprintf( "%-45s %d sec" , dt( 'Max post processing time (max_input_time):' ), $t )); } $t = ini_get ( 'memory_limit' ); if ( $t === "-1" ) { drush_print(sprintf( "%-45s %s" , dt( 'Max memory use (memory_limit):' ), dt( '(unlimited)' ))); } else { drush_print(sprintf( "%-45s %s" , dt( 'Max memory use (memory_limit):' ), $t )); } // Drush runs from the command line interpreter, and that always sets the // execution time to 0. There is no way to get the value a web-invoked // PHP would see. drush_print(sprintf( "%-45s %s" , dt( 'Max execution time (max_execution_time):' ), dt( "(unavailable via drush)" ))); } /*--------------------------------------------------------------------- * * Module configuration - tasks. * *---------------------------------------------------------------------*/ /** * Performs operations to list, run, and delete tasks. * * --delete Delete the indicated task. * --deleteall Delete all scheduled tasks. * --list (default) List all scheduled task entities. * --run Run the scheduled task executor. * * @param int $id * (optional, default = (-1)) The task entity ID to delete. */ function drush_foldershare_tasks( $id = -1) { if ( empty (drush_get_option( 'run' )) === FALSE) { drush_foldershare_tasks_run(); return ; } FolderShareScheduledTask::setTaskExecutionEnabled(FALSE); if ( empty (drush_get_option( 'deleteall' )) === FALSE) { drush_foldershare_tasks_deleteall(); return ; } if ( empty (drush_get_option( 'delete' )) === FALSE) { drush_foldershare_tasks_delete( $id ); return ; } // Default to a list. drush_foldershare_tasks_list(); } /** * Performs an execution of ready tasks. */ function drush_foldershare_tasks_run() { drush_print(dt( 'FolderShare: Executing ready tasks...' )); FolderShareScheduledTask::setTaskExecutionEnabled(TRUE); FolderShareScheduledTask::executeTasks(time()); } /** * Performs a deletion of all tasks. */ function drush_foldershare_tasks_deleteall() { // Explain. drush_print(dt( "FolderShare: Delete all tasks" )); drush_print( '------------------------------------------------------------------------' ); drush_print(dt( "WARNING: Deleting all tasks will leave pending operations incomplete." )); drush_print(dt( "This can stop tasks that are in the middle of deleting, copying," )); drush_print(dt( "moving, and changing the ownership of content. This will leave locks" )); drush_print(dt( "held, items hidden or disabled, and operations unfinished." )); drush_print( "" ); drush_print(dt( " ** This can corrupt the file system **" )); drush_print( "" ); drush_print(dt( "This should be done only when there is something deeply wrong and you" )); drush_print(dt( "are very sure that deleting all tasks is the best thing to do." )); drush_print( "" ); drush_print(dt( "Checking the number of tasks to delete..." )); $n = FolderShareScheduledTask::findNumberOfTasks(); if ( $n === 0) { drush_print(dt( "... none! There are no tasks to delete." )); return ; } drush_print( "" ); $answer = readline(dt( "Are you sure [y|n]? " )); if ( $answer [0] !== 'y' ) { drush_print(dt( "Aborted." )); return ; } // Execute. drush_print( "" ); drush_print(dt( "Deleting all tasks." )); drush_print(dt( " This may take a few minutes..." )); FolderShareScheduledTask::deleteAllTasks(); drush_print( "" ); drush_print(dt( "Done. You should run 'drush foldershare-fsck' immediately to check for file" )); drush_print(dt( "system corruption." )); } /** * Performs a deletion of a selected task. * * @param int $id * The ID of a task to delete. */ function drush_foldershare_tasks_delete( $id ) { // Validate entity ID. $id = (int) $id ; if ( $id < 0) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( ' Missing task ID to delete.' )); return ; } $task = FolderShareScheduledTask::load( $id ); if ( $task === NULL) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( " The task ID @id does not match any known task." , [ '@id' => $id , ])); return ; } // Explain. drush_print(dt( "FolderShare: Delete task" )); drush_print( '------------------------------------------------------------------------' ); drush_print(dt( "WARNING: Deleting a task will leave a pending operation incomplete." )); drush_print(dt( "This can stop task in the middle of deleting, copying, moving,, and" )); drush_print(dt( "changing the ownership of content. This will leave locks held, items" )); drush_print(dt( "hidden or disabled, and operations unfinished." )); drush_print( "" ); drush_print(dt( " ** This can corrupt the file system **" )); drush_print( "" ); // Prompt. $answer = readline(dt( "Are you sure [y|n]? " )); if ( $answer [0] !== 'y' ) { drush_print(dt( "Aborted." )); return ; } // Execute. drush_print( "" ); drush_print(dt( "Deleting task @id..." , [ '@id' => $id ])); $task -> delete (); drush_print( "" ); drush_print(dt( "Done. You should run 'drush foldershare-fsck' immediately to check for file" )); drush_print(dt( "system corruption." )); } /** * Performs a task list. */ function drush_foldershare_tasks_list() { // Table heading. drush_print(dt( 'FolderShare Scheduled tasks' )); drush_print(sprintf( '%10s %-15s %-80s' , dt( 'Task ID' ), dt( 'Requester' ), dt( 'Callback' ))); drush_print( '------------------------------------------------------------------------' ); // Get a list of tasks. $taskIds = FolderShareScheduledTask::findTaskIds(); if ( count ( $taskIds ) === 0) { drush_print(dt( "None." )); return ; } // List each item. foreach ( $taskIds as $id ) { $task = FolderShareScheduledTask::load( $id ); if ( $task === NULL) { // Task does not exist. continue ; } $callback = $task ->getCallback(); $requester = $task ->getRequester(); $parameters = $task ->getParameters(); $comments = $task ->getComments(); $executionTime = $task ->getAccumulatedExecutionTime(); $createdTime = date ( 'Y-m-d H:i:s' , intval ( $task ->getcreatedTime())); $scheduledTime = date ( 'Y-m-d H:i:s' , intval ( $task ->getScheduledTime())); $startTime = date ( 'Y-m-d H:i:s' , intval ( $task ->getStartedTime())); $u = User::load( $requester ); if ( $u === NULL) { $requesterName = sprintf( '%s (%d)' , dt( 'unknown' ), $requester ); } else { $requesterName = sprintf( '%s (%d)' , $u ->getDisplayName(), $requester ); } drush_print(sprintf( '%10d %-15s %-80s' , $id , $requesterName , $callback )); drush_print(sprintf( '%26s First started %s' , "" , $startTime )); drush_print(sprintf( '%26s Current created %s' , "" , $createdTime )); drush_print(sprintf( '%26s Next scheduled %s' , "" , $scheduledTime )); drush_print(sprintf( '%26s Total run time %d sec' , "" , $executionTime )); if ( empty ( $comments ) === FALSE) { drush_print(sprintf( "%26s %s" , "" , $comments )); } if ( empty ( $parameters ) === FALSE) { drush_print(sprintf( "%26s %s = %s" , "" , dt( 'parameters' ), $parameters )); } drush_print( "" ); } } /*--------------------------------------------------------------------- * * Module configuration - usage. * *---------------------------------------------------------------------*/ /** * Operates on the usage table. * * --list (default) List the usage table. * --update Update the usage table now. */ function drush_foldershare_usage() { FolderShareScheduledTask::setTaskExecutionEnabled(FALSE); // // Update usage table. // ------------------- // Immediately update the usage table. if ( empty (drush_get_option( 'update' )) === FALSE) { drush_print(dt( "FolderShare usage statistics update" )); drush_print(dt( " This may take a few minutes..." )); ManageUsageStatistics::updateUsage(); drush_print(dt( "Done." )); return ; } // // List usage table. // ----------------- // Get and present the usage table. $t = ManageUsageStatistics::getLastUpdateTime(); switch ( $t ) { case '' : $t = 'never' ; drush_print(dt( 'FolderShare usage: (never updated)' )); break ; case 'never' : case 'pending' : drush_print(dt( 'FolderShare usage: (never updated)' )); break ; default : if ( $t [0] === '@' ) { $t = date ( 'Y-m-d H:i:s' , intval ( substr ( $t , 1))); } else { $t = date ( 'Y-m-d H:i:s' , intval ( $t )); } drush_print(dt( 'FolderShare usage: (last updated @updated)' , [ '@updated' => $t , ])); break ; } // Table heading. drush_print(sprintf( '%-50s %10s %10s %10s' , dt( 'User' ), dt( 'Folders' ), dt( 'Files' ), dt( 'Bytes' ))); drush_print(sprintf( '%-50s %10s %10s %10s' , '--------------------------------------------------' , '----------' , '----------' , '----------' )); // Get all usage. This has one entry per user. $allUsage = ManageUsageStatistics::getAllUsage(); // List each item. foreach ( $allUsage as $uid => $usage ) { // Load the user entity so we can get the display name. $u = User::load( $uid ); if ( $u === NULL) { $userName = sprintf( '%s (%d)' , dt( 'unknown' ), $uid ); } else { $userName = sprintf( '%s (%d)' , $u ->getDisplayName(), $uid ); } drush_print(sprintf( '%-50s %10d %10d %10d' , $userName , $usage [ 'nFolders' ], $usage [ 'nFiles' ], $usage [ 'nBytes' ])); } } /*--------------------------------------------------------------------- * * Module configuration - version. * *---------------------------------------------------------------------*/ /** * Shows the version number. */ function drush_foldershare_version() { FolderShareScheduledTask::setTaskExecutionEnabled(FALSE); $modules = system_get_info( 'module' ); if (isset( $modules [ 'foldershare' ]) === TRUE) { $version = $modules [ 'foldershare' ][ 'version' ]; drush_print( "FolderShare $version" ); } else { drush_print(sprintf( "FolderShare (%s)" , dt( 'unknown' ))); } } /*--------------------------------------------------------------------- * * Benchmark. * *---------------------------------------------------------------------*/ /** * Benchmark FolderShare. */ function drush_foldershare_benchmark() { FolderShareScheduledTask::setTaskExecutionEnabled(FALSE); if ( empty (drush_get_option( 'config' )) === TRUE && empty (drush_get_option( 'lock' )) === TRUE && empty (drush_get_option( 'system' )) === TRUE && empty (drush_get_option( 'folder' )) === TRUE) { drush_print(dt( "FolderShare: Error" )); drush_print(dt( " No benchmark specified." )); drush_print(dt( ' Type "drush help foldershare-benchmark" for a list.' )); return ; } // Explain. drush_print(dt( "FolderShare: Benchmarks" )); drush_print( '------------------------------------------------------------------------' ); drush_print(dt( "These benchmarks automatically enter and exit maintenance mode." )); drush_print(dt( "If there are non-administrator users connected to the site, they will" )); drush_print(dt( "be blocked from activity during benchmarking." )); drush_print( "" ); // Prompt. $answer = readline(dt( "Are you ready [y|n]? " )); if ( $answer [0] !== 'y' ) { drush_print(dt( "Aborted." )); return ; } drush_print( "" ); $warmUpCount = 2; $benchmarkCount = 10; // Put the site into maintenance mode. $originalMode = \Drupal::state()->get( 'system.maintenance_mode' ); \Drupal::state()->set( 'system.maintenance_mode' , 1); Cache::invalidateTags([ 'rendered' ]); try { if ( empty (drush_get_option( 'config' )) === FALSE) { drush_foldershare_benchmark_config( $warmUpCount , $benchmarkCount ); } elseif ( empty (drush_get_option( 'lock' )) === FALSE) { drush_foldershare_benchmark_lock( $warmUpCount , $benchmarkCount ); } elseif ( empty (drush_get_option( 'folder' )) === FALSE) { drush_foldershare_benchmark_folder( $warmUpCount , $benchmarkCount ); } elseif ( empty (drush_get_option( 'system' )) === FALSE) { drush_foldershare_benchmark_system( $warmUpCount , $benchmarkCount ); } } catch (\Exception $e ) { drush_print( $e ); } // Restore the original mode. \Drupal::state()->set( 'system.maintenance_mode' , $originalMode ); } /** * Benchmarks get/set of FolderShare configuration. * * All module configuration are managed by the Settings class, which * gets and sets values in a configuration saved to the database by Drupal * core. Since all of them are treated the same, this method picks one and * benchmarks get and set operations using it. * * @param int $warmUpCount * The number of passes during a warm-up phase. * @param int $benchmarkCount * The number of passes during a benchmark phase. */ function drush_foldershare_benchmark_config( int $warmUpCount , int $benchmarkCount ) { drush_print( "FolderShare: Benchmark configuration get/set" ); drush_print( "----------------------------------------------------------------" ); drush_print( "This benchmark measures the time to get and set configuration" ); drush_print( "values managed by FolderShare's Settings class." ); drush_print( "" ); // Save the original value. $originalValue = Settings::getStatusPollingInterval(); // // Get setting. // -----------. $bogusValue = 0; for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $bogusValue += Settings::getStatusPollingInterval(); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { $bogusValue += Settings::getStatusPollingInterval(); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Get configuration" , $tdelta )); // // Set setting. // -----------. $newValue = $originalValue + 0.1; for ( $i = 0; $i < $warmUpCount ; ++ $i ) { Settings::setStatusPollingInterval( $newValue ); $newValue += 0.1; } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { Settings::setStatusPollingInterval( $newValue ); $newValue += 0.1; } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Set configuration" , $tdelta )); // Restore the original value. Settings::setStatusPollingInterval( $originalValue ); } /** * Benchmarks lock and release. * * All major FolderShare operations (e.g. copy, move, delete) lock a root * folder and/or a root list, then release the lock. * * @param int $warmUpCount * The number of passes during a warm-up phase. * @param int $benchmarkCount * The number of passes during a benchmark phase. */ function drush_foldershare_benchmark_lock( int $warmUpCount , int $benchmarkCount ) { drush_print( "FolderShare: Benchmark lock and release" ); drush_print( "----------------------------------------------------------------" ); drush_print( "This benchmark measures the time to lock a root folder or a" ); drush_print( "root list, then release the lock. Since locks do not involve" ); drush_print( "entities, just entity IDs, these benchmarks use a bogus ID." ); drush_print( "" ); // // Lock root. // ---------. for ( $i = 0; $i < $warmUpCount ; ++ $i ) { FolderShare::acquireRootOperationLock(0); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { FolderShare::acquireRootOperationLock(0); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Root operation lock" , $tdelta )); // // Unlock root. // -----------. for ( $i = 0; $i < $warmUpCount ; ++ $i ) { FolderShare::releaseRootOperationLock(0); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { FolderShare::releaseRootOperationLock(0); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Root operation release" , $tdelta )); // // Lock root list. // --------------. for ( $i = 0; $i < $warmUpCount ; ++ $i ) { FolderShare::acquireUserRootListLock(0); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { FolderShare::acquireUserRootListLock(0); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Root list lock" , $tdelta )); // // Unlock root list. // ----------------. for ( $i = 0; $i < $warmUpCount ; ++ $i ) { FolderShare::releaseUserRootListLock(0); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { FolderShare::releaseUserRootListLock(0); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Root list release" , $tdelta )); } /** * Benchmarks folder operations. * * Folders exist solely within the database. This method benchmarks creating, * deleting, loading, etc on folders. No file operations take place. * * @param int $warmUpCount * The number of passes during a warm-up phase. * @param int $benchmarkCount * The number of passes during a benchmark phase. */ function drush_foldershare_benchmark_folder( int $warmUpCount , int $benchmarkCount ) { drush_print( "FolderShare: Benchmark folder operations" ); drush_print( "----------------------------------------------------------------" ); drush_print( "This benchmark measures the time to create, delete, load," ); drush_print( "copy, and move individual empty folders." ); drush_print( "" ); // // Create root folders. // -------------------. $created = []; for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $created [] = FolderShare::createRootFolder(); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { $created [] = FolderShare::createRootFolder(); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Create root folder" , $tdelta )); // // Load root folders from memory cache. // -----------------------------------. // Evidentally, created items are NOT automatically added to the storage // manager's memory and database caches. An entry is only added to those // caches if an item is loaded. So, start with a redundant load of the // same entities created above. foreach ( $created as $item ) { FolderShare::load( $item ->id()); } $n = 0; for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $item = FolderShare::load( $created [ $n ++]->id()); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { $item = FolderShare::load( $created [ $n ++]->id()); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Load root folder (memory cached)" , $tdelta )); // // Load root folders from database cache. // -------------------------------------. // Clear the memory cache. This should leave the storage manager's database // cache in place and subsequent loads will load from it. \Drupal::service( 'entity.memory_cache' )->deleteAll(); $n = 0; for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $item = FolderShare::load( $created [ $n ++]->id()); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { $item = FolderShare::load( $created [ $n ++]->id()); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Load root folder (DB cached)" , $tdelta )); // // Load root folders from database (uncached). // ------------------------------------------. // Reseting the storage manager's cache clears everything from memory and // database caches. Further loads must assemble the entity from assorted // database tables. \Drupal::entityTypeManager()->getStorage( 'foldershare' )->resetCache(); $n = 0; for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $item = FolderShare::load( $created [ $n ++]->id()); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { $item = FolderShare::load( $created [ $n ++]->id()); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Load root folder (uncached)" , $tdelta )); // // Duplicate root folders. // ----------------------. $n = 0; for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $created [] = $created [ $n ++]->duplicate(); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { $created [] = $created [ $n ++]->duplicate(); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Duplicate root folder" , $tdelta )); // // Change owner on root folders. // ----------------------------. for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $item = $created [ $i ]; $item ->changeOwnerId(1, FALSE); } $nCreated = count ( $created ); $tStart = microtime(TRUE); foreach ( $created as $item ) { $item ->changeOwnerId(1, FALSE); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $nCreated ; drush_print(sprintf( " %-35s %10.6f sec" , "Change owner on root folder" , $tdelta )); // // Delete root folders. // -------------------. for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $item = array_shift ( $created ); $item -> delete (); } $nCreated = count ( $created ); $tStart = microtime(TRUE); foreach ( $created as $item ) { $item -> delete (); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $nCreated ; drush_print(sprintf( " %-35s %10.6f sec" , "Delete root folder" , $tdelta )); drush_print( "" ); // // Create subfolders. // -----------------. $parent = FolderShare::createRootFolder(); $created = []; for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $created [] = $parent ->createFolder(); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { $created [] = $parent ->createFolder(); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Create subfolder" , $tdelta )); // // Load subfolders from memory cache. // ----------------------------------. // See comments above on the memory cache. foreach ( $created as $item ) { FolderShare::load( $item ->id()); } $n = 0; for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $item = FolderShare::load( $created [ $n ++]->id()); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { $item = FolderShare::load( $created [ $n ++]->id()); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Load subfolder (memory cached)" , $tdelta )); // // Load sub folders from database cache. // ------------------------------------. // See comments above on the database cache. \Drupal::service( 'entity.memory_cache' )->deleteAll(); $n = 0; for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $item = FolderShare::load( $created [ $n ++]->id()); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { $item = FolderShare::load( $created [ $n ++]->id()); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Load subfolder (DB cached)" , $tdelta )); // // Load subfolders from database (uncached). // ----------------------------------------. // See comments above on reseting the cache. \Drupal::entityTypeManager()->getStorage( 'foldershare' )->resetCache(); $n = 0; for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $item = FolderShare::load( $created [ $n ++]->id()); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { $item = FolderShare::load( $created [ $n ++]->id()); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Load subfolder (uncached)" , $tdelta )); // // Duplicate subfolders. // --------------------. $n = 0; for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $created [] = $created [ $n ++]->duplicate(); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { $created [] = $created [ $n ++]->duplicate(); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Duplicate subfolder" , $tdelta )); // // Change owner on subfolders. // --------------------------. for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $item = $created [ $i ]; $item ->changeOwnerId(1, FALSE); } $nCreated = count ( $created ); $tStart = microtime(TRUE); foreach ( $created as $item ) { $item ->changeOwnerId(1, FALSE); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $nCreated ; drush_print(sprintf( " %-35s %10.6f sec" , "Change owner on subfolder" , $tdelta )); // // Delete subfolders. // -----------------. for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $item = array_shift ( $created ); $item -> delete (); } $nCreated = count ( $created ); $tStart = microtime(TRUE); foreach ( $created as $item ) { $item -> delete (); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $nCreated ; drush_print(sprintf( " %-35s %10.6f sec" , "Delete subfolder" , $tdelta )); // Clean up. $parent -> delete (); $created = []; } /** * Benchmarks getting system values. * * Getting PHP ini directive values, the current time, the current memory * usage are all queries of system values. * * @param int $warmUpCount * The number of passes during a warm-up phase. * @param int $benchmarkCount * The number of passes during a benchmark phase. */ function drush_foldershare_benchmark_system( int $warmUpCount , int $benchmarkCount ) { drush_print( "FolderShare: Benchmark getting system values" ); drush_print( "----------------------------------------------------------------" ); drush_print( "This benchmark measures the time to get system values, such as" ); drush_print( "PHP ini directive values, the current time, the current memory" ); drush_print( "usage, and so on." ); drush_print( "" ); // // Get ini value. // -------------. $bogusValue = 0; for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $bogusValue += ini_get ( 'max_execution_time' ); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { $bogusValue += ini_get ( 'max_execution_time' ); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Get ini value" , $tdelta )); // // Get time. // --------. for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $bogusValue += time(); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { $bogusValue += time(); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Get time" , $tdelta )); // // Get memory usage. // ----------------. for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $bogusValue += memory_get_usage(); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { $bogusValue += memory_get_usage(); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Get memory usage" , $tdelta )); // // Garbage collect (no garbage). // ----------------------------. for ( $i = 0; $i < $warmUpCount ; ++ $i ) { gc_collect_cycles(); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { gc_collect_cycles(); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Garbage collect (no garbage)" , $tdelta )); // // Garbage collect (some garbage). // ----------------------------. for ( $i = 0; $i < $warmUpCount ; ++ $i ) { $junk = []; for ( $j = 0; $j < 100; ++ $j ) { $junk [] = new stdClass(); } for ( $j = 0; $j < 100; ++ $j ) { unset( $junk [ $j ]); } gc_collect_cycles(); } $tStart = microtime(TRUE); for ( $i = 0; $i < $benchmarkCount ; ++ $i ) { $junk = []; for ( $j = 0; $j < 100; ++ $j ) { $junk [] = new stdClass(); } for ( $j = 0; $j < 100; ++ $j ) { unset( $junk [ $j ]); } gc_collect_cycles(); } $tEnd = microtime(TRUE); $tdelta = ( $tEnd - $tStart ) / $benchmarkCount ; drush_print(sprintf( " %-35s %10.6f sec" , "Garbage collect (with garbage)" , $tdelta )); } |