original_string: protected function generateStatementFromPropertiesAndTypesLists(
          array $selectPropertyIds,
          array $fromTypes,
          $whereClause,
          array $orderByPropertyIds
      ) {
          $statementString = 'SELECT ' . $this->generateStatementPropertyList($selectPropertyIds, false);
  
          $primaryTable = array_shift($fromTypes);
          list ($primaryTableQueryName, $primaryAlias) = $this->getQueryNameAndAliasForType($primaryTable, 'primary');
  
          $statementString .= ' FROM ' . $primaryTableQueryName . ' ' . $primaryAlias;
  
          while (count($fromTypes) > 0) {
              $secondaryTable = array_shift($fromTypes);
              /*
               * we build an automatic alias here, a simple one-byte ASCII value
               * generated based on remaining tables. If 26 tables remain, a "z"
               * is generated. If 1 table remains, an "a" is generated. The alias
               * is, unfortunately, required for the JOIN to work correctly. It
               * only gets used if the type string does not contain an alias.
               */
              $alias = chr(97 + count($fromTypes));
              list ($secondaryTableQueryName, $alias) = $this->getQueryNameAndAliasForType($secondaryTable, $alias);
              $statementString .= ' JOIN ' . $secondaryTableQueryName . ' AS ' . $alias .
                  ' ON ' . $primaryAlias . '.cmis:objectId = ' . $alias . '.cmis:objectId';
          }
  
          if (trim((string) $whereClause)) {
              $statementString .= ' WHERE ' . trim($whereClause);
          }
  
          if (!empty($orderByPropertyIds)) {
              $statementString .= ' ORDER BY ' . $this->generateStatementPropertyList($orderByPropertyIds, true);
          }
          return trim($statementString);
      }
code: protected function generateStatementFromPropertiesAndTypesLists(
          array $selectPropertyIds,
          array $fromTypes,
          $whereClause,
          array $orderByPropertyIds
      ) {
          $statementString = 'SELECT ' . $this->generateStatementPropertyList($selectPropertyIds, false);
  
          $primaryTable = array_shift($fromTypes);
          list ($primaryTableQueryName, $primaryAlias) = $this->getQueryNameAndAliasForType($primaryTable, 'primary');
  
          $statementString .= ' FROM ' . $primaryTableQueryName . ' ' . $primaryAlias;
  
          while (count($fromTypes) > 0) {
              $secondaryTable = array_shift($fromTypes);
              /*
               * we build an automatic alias here, a simple one-byte ASCII value
               * generated based on remaining tables. If 26 tables remain, a "z"
               * is generated. If 1 table remains, an "a" is generated. The alias
               * is, unfortunately, required for the JOIN to work correctly. It
               * only gets used if the type string does not contain an alias.
               */
              $alias = chr(97 + count($fromTypes));
              list ($secondaryTableQueryName, $alias) = $this->getQueryNameAndAliasForType($secondaryTable, $alias);
              $statementString .= ' JOIN ' . $secondaryTableQueryName . ' AS ' . $alias .
                  ' ON ' . $primaryAlias . '.cmis:objectId = ' . $alias . '.cmis:objectId';
          }
  
          if (trim((string) $whereClause)) {
              $statementString .= ' WHERE ' . trim($whereClause);
          }
  
          if (!empty($orderByPropertyIds)) {
              $statementString .= ' ORDER BY ' . $this->generateStatementPropertyList($orderByPropertyIds, true);
          }
          return trim($statementString);
      }
code_tokens: protected function generateStatementFromPropertiesAndTypesLists ( array $ selectPropertyIds , array $ fromTypes , $ whereClause , array $ orderByPropertyIds ) { $ statementString = 'SELECT ' . $ this -> generateStatementPropertyList ( $ selectPropertyIds , false ) ; $ primaryTable = array_shift ( $ fromTypes ) ; list ( $ primaryTableQueryName , $ primaryAlias ) = $ this -> getQueryNameAndAliasForType ( $ primaryTable , 'primary' ) ; $ statementString .= ' FROM ' . $ primaryTableQueryName . ' ' . $ primaryAlias ; while ( count ( $ fromTypes ) > 0 ) { $ secondaryTable = array_shift ( $ fromTypes ) ; /*
               * we build an automatic alias here, a simple one-byte ASCII value
               * generated based on remaining tables. If 26 tables remain, a "z"
               * is generated. If 1 table remains, an "a" is generated. The alias
               * is, unfortunately, required for the JOIN to work correctly. It
               * only gets used if the type string does not contain an alias.
               */ $ alias = chr ( 97 + count ( $ fromTypes ) ) ; list ( $ secondaryTableQueryName , $ alias ) = $ this -> getQueryNameAndAliasForType ( $ secondaryTable , $ alias ) ; $ statementString .= ' JOIN ' . $ secondaryTableQueryName . ' AS ' . $ alias . ' ON ' . $ primaryAlias . '.cmis:objectId = ' . $ alias . '.cmis:objectId' ; } if ( trim ( ( string ) $ whereClause ) ) { $ statementString .= ' WHERE ' . trim ( $ whereClause ) ; } if ( ! empty ( $ orderByPropertyIds ) ) { $ statementString .= ' ORDER BY ' . $ this -> generateStatementPropertyList ( $ orderByPropertyIds , true ) ; } return trim ( $ statementString ) ; }
docstring: Generates a statement based on input criteria, with the necessary
  JOINs in place for selecting attributes related to all provided types.
  
  @param array $selectPropertyIds An array PropertyDefinitionInterface
  or strings, can be mixed. When strings are provided those can be
  either the actual ID of the property or the query name thereof.
  @param array $fromTypes An array of TypeDefinitionInterface or strings,
  can be mixed. When strings are provided those can be either the
  actual ID of the type, or it can be the query name thereof. If
  an array of arrays is provided, each array is expected to contain
  a TypeDefinition or string as first member and an alias as second.
  @param string|null $whereClause If searching by custom clause, provide here.
  @param array $orderByPropertyIds List of property IDs by which to sort.
  Each value can be either a PropertyDefinitionInterface instance,
  a string (in which case, ID or queryName) or an array of a string
  or PropertyDefinition as first member and ASC or DESC as second.
  E.g. valid strings: "cm:title ASC", "cm:title", "P:cm:title".
  Valid arrays: [PropertyDefinitionInterface, "ASC"], ["cm:title", "ASC"]
  @return string
docstring_tokens: Generates a statement based on input criteria with the necessary JOINs in place for selecting attributes related to all provided types .