original_string: protected static function get_nested_expiry_info_from_sql(string $sql, array $params) : array {
          global $DB;
  
          $fulllist = $DB->get_recordset_sql($sql, $params);
          $datalist = [];
          $expiredcontents = [];
          $pathstoskip = [];
  
          $userpurpose = data_registry::get_effective_contextlevel_value(CONTEXT_USER, 'purpose');
          foreach ($fulllist as $record) {
              \context_helper::preload_from_record($record);
              $context = \context::instance_by_id($record->id, false);
  
              if (!self::is_eligible_for_deletion($pathstoskip, $context)) {
                  // We should skip this context, and therefore all of it's children.
                  $datalist = array_filter($datalist, function($data, $path) use ($context) {
                      // Remove any child of this context.
                      // Technically this should never be fulfilled because the query is ordered in path DESC, but is kept
                      // in to be certain.
                      return (false === strpos($path, "{$context->path}/"));
                  }, ARRAY_FILTER_USE_BOTH);
  
                  if ($record->expiredctxid) {
                      // There was previously an expired context record.
                      // Delete it to be on the safe side.
                      $expiredcontext = new expired_context(null, expired_context::extract_record($record, 'expiredctx'));
                      $expiredcontext->delete();
                  }
                  continue;
              }
  
              if ($context instanceof \context_user) {
                  $purpose = $userpurpose;
              } else {
                  $purposevalue = $record->purposeid !== null ? $record->purposeid : context_instance::NOTSET;
                  $purpose = api::get_effective_context_purpose($context, $purposevalue);
              }
  
              if ($context instanceof \context_user && !empty($record->userdeleted)) {
                  $expiryinfo = static::get_expiry_info($purpose, $record->userdeleted);
              } else {
                  $expiryinfo = static::get_expiry_info($purpose, $record->expirydate);
              }
  
              foreach ($datalist as $path => $data) {
                  // Merge with already-processed children.
                  if (strpos($path, $context->path) !== 0) {
                      continue;
                  }
  
                  $expiryinfo->merge_with_child($data->info);
              }
  
              $datalist[$context->path] = (object) [
                  'context' => $context,
                  'record' => $record,
                  'purpose' => $purpose,
                  'info' => $expiryinfo,
              ];
          }
          $fulllist->close();
  
          return $datalist;
      }
code: protected static function get_nested_expiry_info_from_sql(string $sql, array $params) : array {
          global $DB;
  
          $fulllist = $DB->get_recordset_sql($sql, $params);
          $datalist = [];
          $expiredcontents = [];
          $pathstoskip = [];
  
          $userpurpose = data_registry::get_effective_contextlevel_value(CONTEXT_USER, 'purpose');
          foreach ($fulllist as $record) {
              \context_helper::preload_from_record($record);
              $context = \context::instance_by_id($record->id, false);
  
              if (!self::is_eligible_for_deletion($pathstoskip, $context)) {
                  // We should skip this context, and therefore all of it's children.
                  $datalist = array_filter($datalist, function($data, $path) use ($context) {
                      // Remove any child of this context.
                      // Technically this should never be fulfilled because the query is ordered in path DESC, but is kept
                      // in to be certain.
                      return (false === strpos($path, "{$context->path}/"));
                  }, ARRAY_FILTER_USE_BOTH);
  
                  if ($record->expiredctxid) {
                      // There was previously an expired context record.
                      // Delete it to be on the safe side.
                      $expiredcontext = new expired_context(null, expired_context::extract_record($record, 'expiredctx'));
                      $expiredcontext->delete();
                  }
                  continue;
              }
  
              if ($context instanceof \context_user) {
                  $purpose = $userpurpose;
              } else {
                  $purposevalue = $record->purposeid !== null ? $record->purposeid : context_instance::NOTSET;
                  $purpose = api::get_effective_context_purpose($context, $purposevalue);
              }
  
              if ($context instanceof \context_user && !empty($record->userdeleted)) {
                  $expiryinfo = static::get_expiry_info($purpose, $record->userdeleted);
              } else {
                  $expiryinfo = static::get_expiry_info($purpose, $record->expirydate);
              }
  
              foreach ($datalist as $path => $data) {
                  // Merge with already-processed children.
                  if (strpos($path, $context->path) !== 0) {
                      continue;
                  }
  
                  $expiryinfo->merge_with_child($data->info);
              }
  
              $datalist[$context->path] = (object) [
                  'context' => $context,
                  'record' => $record,
                  'purpose' => $purpose,
                  'info' => $expiryinfo,
              ];
          }
          $fulllist->close();
  
          return $datalist;
      }
code_tokens: protected static function get_nested_expiry_info_from_sql ( string $ sql , array $ params ) : array { global $ DB ; $ fulllist = $ DB -> get_recordset_sql ( $ sql , $ params ) ; $ datalist = [ ] ; $ expiredcontents = [ ] ; $ pathstoskip = [ ] ; $ userpurpose = data_registry :: get_effective_contextlevel_value ( CONTEXT_USER , 'purpose' ) ; foreach ( $ fulllist as $ record ) { \ context_helper :: preload_from_record ( $ record ) ; $ context = \ context :: instance_by_id ( $ record -> id , false ) ; if ( ! self :: is_eligible_for_deletion ( $ pathstoskip , $ context ) ) { // We should skip this context, and therefore all of it's children. $ datalist = array_filter ( $ datalist , function ( $ data , $ path ) use ( $ context ) { // Remove any child of this context. // Technically this should never be fulfilled because the query is ordered in path DESC, but is kept // in to be certain. return ( false === strpos ( $ path , "{$context->path}/" ) ) ; } , ARRAY_FILTER_USE_BOTH ) ; if ( $ record -> expiredctxid ) { // There was previously an expired context record. // Delete it to be on the safe side. $ expiredcontext = new expired_context ( null , expired_context :: extract_record ( $ record , 'expiredctx' ) ) ; $ expiredcontext -> delete ( ) ; } continue ; } if ( $ context instanceof \ context_user ) { $ purpose = $ userpurpose ; } else { $ purposevalue = $ record -> purposeid !== null ? $ record -> purposeid : context_instance :: NOTSET ; $ purpose = api :: get_effective_context_purpose ( $ context , $ purposevalue ) ; } if ( $ context instanceof \ context_user && ! empty ( $ record -> userdeleted ) ) { $ expiryinfo = static :: get_expiry_info ( $ purpose , $ record -> userdeleted ) ; } else { $ expiryinfo = static :: get_expiry_info ( $ purpose , $ record -> expirydate ) ; } foreach ( $ datalist as $ path => $ data ) { // Merge with already-processed children. if ( strpos ( $ path , $ context -> path ) !== 0 ) { continue ; } $ expiryinfo -> merge_with_child ( $ data -> info ) ; } $ datalist [ $ context -> path ] = ( object ) [ 'context' => $ context , 'record' => $ record , 'purpose' => $ purpose , 'info' => $ expiryinfo , ] ; } $ fulllist -> close ( ) ; return $ datalist ; }
docstring: Get the full nested set of expiry data given appropriate SQL.
  Only contexts which have expired will be included.
  
  @param   string      $sql The SQL used to select the nested information.
  @param   array       $params The params required by the SQL.
  @return  \stdClass[]
docstring_tokens: Get the full nested set of expiry data given appropriate SQL . Only contexts which have expired will be included .