You are here

private function PHPExcel_Reader_Excel5::_readHyperLink in Loft Data Grids 7.2

Same name and namespace in other branches
  1. 6.2 vendor/phpoffice/phpexcel/Classes/PHPExcel/Reader/Excel5.php \PHPExcel_Reader_Excel5::_readHyperLink()

* Read HYPERLINK record

1 call to PHPExcel_Reader_Excel5::_readHyperLink()
PHPExcel_Reader_Excel5::load in vendor/phpoffice/phpexcel/Classes/PHPExcel/Reader/Excel5.php
* Loads PHPExcel from file * *

File

vendor/phpoffice/phpexcel/Classes/PHPExcel/Reader/Excel5.php, line 4485

Class

PHPExcel_Reader_Excel5
PHPExcel_Reader_Excel5

Code

private function _readHyperLink() {
  $length = self::_GetInt2d($this->_data, $this->_pos + 2);
  $recordData = $this
    ->_readRecordData($this->_data, $this->_pos + 4, $length);

  // move stream pointer forward to next record
  $this->_pos += 4 + $length;
  if (!$this->_readDataOnly) {

    // offset: 0; size: 8; cell range address of all cells containing this hyperlink
    try {
      $cellRange = $this
        ->_readBIFF8CellRangeAddressFixed($recordData, 0, 8);
    } catch (PHPExcel_Exception $e) {
      return;
    }

    // offset: 8, size: 16; GUID of StdLink
    // offset: 24, size: 4; unknown value
    // offset: 28, size: 4; option flags
    // bit: 0; mask: 0x00000001; 0 = no link or extant, 1 = file link or URL
    $isFileLinkOrUrl = (0x1 & self::_GetInt2d($recordData, 28)) >> 0;

    // bit: 1; mask: 0x00000002; 0 = relative path, 1 = absolute path or URL
    $isAbsPathOrUrl = (0x1 & self::_GetInt2d($recordData, 28)) >> 1;

    // bit: 2 (and 4); mask: 0x00000014; 0 = no description
    $hasDesc = (0x14 & self::_GetInt2d($recordData, 28)) >> 2;

    // bit: 3; mask: 0x00000008; 0 = no text, 1 = has text
    $hasText = (0x8 & self::_GetInt2d($recordData, 28)) >> 3;

    // bit: 7; mask: 0x00000080; 0 = no target frame, 1 = has target frame
    $hasFrame = (0x80 & self::_GetInt2d($recordData, 28)) >> 7;

    // bit: 8; mask: 0x00000100; 0 = file link or URL, 1 = UNC path (inc. server name)
    $isUNC = (0x100 & self::_GetInt2d($recordData, 28)) >> 8;

    // offset within record data
    $offset = 32;
    if ($hasDesc) {

      // offset: 32; size: var; character count of description text
      $dl = self::_GetInt4d($recordData, 32);

      // offset: 36; size: var; character array of description text, no Unicode string header, always 16-bit characters, zero terminated
      $desc = self::_encodeUTF16(substr($recordData, 36, 2 * ($dl - 1)), false);
      $offset += 4 + 2 * $dl;
    }
    if ($hasFrame) {
      $fl = self::_GetInt4d($recordData, $offset);
      $offset += 4 + 2 * $fl;
    }

    // detect type of hyperlink (there are 4 types)
    $hyperlinkType = null;
    if ($isUNC) {
      $hyperlinkType = 'UNC';
    }
    else {
      if (!$isFileLinkOrUrl) {
        $hyperlinkType = 'workbook';
      }
      else {
        if (ord($recordData[$offset]) == 0x3) {
          $hyperlinkType = 'local';
        }
        else {
          if (ord($recordData[$offset]) == 0xe0) {
            $hyperlinkType = 'URL';
          }
        }
      }
    }
    switch ($hyperlinkType) {
      case 'URL':

        // section 5.58.2: Hyperlink containing a URL
        // e.g. http://example.org/index.php
        // offset: var; size: 16; GUID of URL Moniker
        $offset += 16;

        // offset: var; size: 4; size (in bytes) of character array of the URL including trailing zero word
        $us = self::_GetInt4d($recordData, $offset);
        $offset += 4;

        // offset: var; size: $us; character array of the URL, no Unicode string header, always 16-bit characters, zero-terminated
        $url = self::_encodeUTF16(substr($recordData, $offset, $us - 2), false);
        $nullOffset = strpos($url, 0x0);
        if ($nullOffset) {
          $url = substr($url, 0, $nullOffset);
        }
        $url .= $hasText ? '#' : '';
        $offset += $us;
        break;
      case 'local':

        // section 5.58.3: Hyperlink to local file
        // examples:
        //   mydoc.txt
        //   ../../somedoc.xls#Sheet!A1
        // offset: var; size: 16; GUI of File Moniker
        $offset += 16;

        // offset: var; size: 2; directory up-level count.
        $upLevelCount = self::_GetInt2d($recordData, $offset);
        $offset += 2;

        // offset: var; size: 4; character count of the shortened file path and name, including trailing zero word
        $sl = self::_GetInt4d($recordData, $offset);
        $offset += 4;

        // offset: var; size: sl; character array of the shortened file path and name in 8.3-DOS-format (compressed Unicode string)
        $shortenedFilePath = substr($recordData, $offset, $sl);
        $shortenedFilePath = self::_encodeUTF16($shortenedFilePath, true);
        $shortenedFilePath = substr($shortenedFilePath, 0, -1);

        // remove trailing zero
        $offset += $sl;

        // offset: var; size: 24; unknown sequence
        $offset += 24;

        // extended file path
        // offset: var; size: 4; size of the following file link field including string lenth mark
        $sz = self::_GetInt4d($recordData, $offset);
        $offset += 4;

        // only present if $sz > 0
        if ($sz > 0) {

          // offset: var; size: 4; size of the character array of the extended file path and name
          $xl = self::_GetInt4d($recordData, $offset);
          $offset += 4;

          // offset: var; size 2; unknown
          $offset += 2;

          // offset: var; size $xl; character array of the extended file path and name.
          $extendedFilePath = substr($recordData, $offset, $xl);
          $extendedFilePath = self::_encodeUTF16($extendedFilePath, false);
          $offset += $xl;
        }

        // construct the path
        $url = str_repeat('..\\', $upLevelCount);
        $url .= $sz > 0 ? $extendedFilePath : $shortenedFilePath;

        // use extended path if available
        $url .= $hasText ? '#' : '';
        break;
      case 'UNC':

        // section 5.58.4: Hyperlink to a File with UNC (Universal Naming Convention) Path
        // todo: implement
        return;
      case 'workbook':

        // section 5.58.5: Hyperlink to the Current Workbook
        // e.g. Sheet2!B1:C2, stored in text mark field
        $url = 'sheet://';
        break;
      default:
        return;
    }
    if ($hasText) {

      // offset: var; size: 4; character count of text mark including trailing zero word
      $tl = self::_GetInt4d($recordData, $offset);
      $offset += 4;

      // offset: var; size: var; character array of the text mark without the # sign, no Unicode header, always 16-bit characters, zero-terminated
      $text = self::_encodeUTF16(substr($recordData, $offset, 2 * ($tl - 1)), false);
      $url .= $text;
    }

    // apply the hyperlink to all the relevant cells
    foreach (PHPExcel_Cell::extractAllCellReferencesInRange($cellRange) as $coordinate) {
      $this->_phpSheet
        ->getCell($coordinate)
        ->getHyperLink()
        ->setUrl($url);
    }
  }
}