[ Index ]

PHP Cross Reference of PHK Manager

title

Body

[close]

/PHK/Build/ -> Creator.php (source)

   1  <?php
   2  //=============================================================================
   3  //
   4  // Copyright Francois Laupretre <phk@tekwire.net>
   5  //
   6  //   Licensed under the Apache License, Version 2.0 (the "License");
   7  //   you may not use this file except in compliance with the License.
   8  //   You may obtain a copy of the License at
   9  //
  10  //       http://www.apache.org/licenses/LICENSE-2.0
  11  //
  12  //   Unless required by applicable law or agreed to in writing, software
  13  //   distributed under the License is distributed on an "AS IS" BASIS,
  14  //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15  //   See the License for the specific language governing permissions and
  16  //   limitations under the License.
  17  //
  18  //=============================================================================
  19  /**
  20  * @copyright Francois Laupretre <phk@tekwire.net>
  21  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, V 2.0
  22  * @category PHK
  23  * @package PHK
  24  *///==========================================================================
  25  
  26  namespace PHK\Build {
  27  
  28  if (!class_exists('PHK\Build\Creator',false))
  29  {
  30  //============================================================================
  31  /**
  32  * The package creator class
  33  *
  34  * Note: If this file is part of a PHK package (usual case), it is
  35  * absolutely mandatory that Automap and PHK classes as package's files
  36  * are the same as the Automap and PHK classes included in the prolog. Which
  37  * means that the package must be generated from its files. If it is not the
  38  * case, packages generated from this creator package will display wrong version
  39  * information.
  40  *
  41  * API status: Public
  42  * Included in the PHK PHP runtime: No
  43  * Implemented in the extension: No
  44  *///==========================================================================
  45  
  46  class Creator extends \PHK\Base
  47  {
  48  const MIN_RUNTIME_VERSION='3.0.0'; // The minimum version of PHK runtime able to
  49      // understand the packages I produce. Checked against PHK\Base::RUNTIME_VERSION
  50      // or, if PECL, PHP_PHK_VERSION.
  51  
  52  //-----
  53  
  54  public $prolog=null;
  55  public $code=null;
  56  private $interp='';
  57  
  58  //-----
  59  // init a new empty package.
  60  
  61  public function __construct($mnt,$path,$flags)
  62  {
  63  parent::__construct(null,$mnt,$path,$flags,time());
  64  
  65  $this->options=array();
  66  $this->buildInfo=array('build_timestamp' => time());
  67  }
  68  
  69  //---------
  70  
  71  public function ftree()
  72  {
  73  return $this->proxy()->ftree();
  74  }
  75  
  76  //---------
  77  
  78  public function setOptions($opt)
  79  {
  80  $this->options=$opt;
  81  }
  82  
  83  //---------
  84  
  85  public function updateOption($name,$a)
  86  {
  87  $this->options[$name]=$a;
  88  }
  89  
  90  //---------
  91  
  92  public function updateBuildInfo($name,$a)
  93  {
  94  $this->buildInfo[$name]=$a;
  95  }
  96  
  97  //---------
  98  // Allows to use an alternate prolog
  99  
 100  public function setProlog($data)
 101  {
 102  $this->prolog=$data;
 103  }
 104  
 105  //---------
 106  
 107  private function processPhpCode(&$buffer)
 108  {
 109  $buffer=str_replace('?><?php','',$buffer);
 110  $buffer=str_replace("?>\n<?php",'',$buffer);
 111  
 112  foreach (array('creator','plain_file') as $pcode)
 113      {
 114      if (!$this->option("prolog_code_$pcode"))
 115          {
 116          $token=strtoupper($pcode);
 117          while (($pos=strpos($buffer,'<'.$token.'>'))!==false)
 118              {
 119              if (($pos2=strpos($buffer,'</'.$token.'>',$pos))===false)
 120                  throw new \Exception('Cannot find end of <'.$token.'> section');
 121              $buffer=substr_replace($buffer,'',$pos,$pos2-$pos+15);
 122              }
 123          }
 124      }
 125  
 126  // Strip whitespaces from the prolog
 127  
 128  if (!$this->option('plain_prolog'))
 129      {
 130      $buffer=\PHK\Virtual\File::stripWhitespaces($buffer);
 131      }
 132  }
 133  
 134  //---------
 135  // Build runtime PHP code
 136  //-- $dir= base dir where files are stored. In a package, it is the package's
 137  //-- base URI, otherwise, it is the base of the source tree.
 138  
 139  public function buildPhpCode($dir)
 140  {
 141  \Phool\Display::trace('Building PHP runtime');
 142  
 143  $this->code='';
 144  
 145  $automap_base=$dir;
 146  if (! \PHK\Mgr::isPhkUri(__FILE__)) $automap_base .= '/external/automap';
 147  $this->code .= \PHK\Tools\Util::readFile($automap_base.'/src/Automap/Mgr.php');
 148  $this->code .= \PHK\Tools\Util::readFile($automap_base.'/src/Automap/Tools/Display.php');
 149  $this->code .= \PHK\Tools\Util::readFile($automap_base.'/src/Automap/Map.php');
 150  $this->code .= \PHK\Tools\Util::readFile($automap_base.'/src/Automap/Tools/Check.php');
 151  
 152  $this->code .= \PHK\Tools\Util::readFile($dir.'/src/PHK/Tools/Util.php');
 153  $this->code .= \PHK\Tools\Util::readFile($dir.'/src/PHK/PkgFile.php');
 154  $this->code .= \PHK\Tools\Util::readFile($dir.'/src/PHK/Cache.php');
 155  $this->code .= \PHK\Tools\Util::readFile($dir.'/src/PHK/Proxy.php');
 156  $this->code .= \PHK\Tools\Util::readFile($dir.'/src/PHK/Mgr.php');
 157  $this->code .= \PHK\Tools\Util::readFile($dir.'/src/PHK/Base.php');
 158  $this->code .= \PHK\Tools\Util::readFile($dir.'/src/PHK.php');
 159  $this->code .= \PHK\Tools\Util::readFile($dir.'/src/PHK/Backend.php');
 160  $this->code .= \PHK\Tools\Util::readFile($dir.'/src/PHK/Stream/Wrapper.php');
 161  $this->code .= \PHK\Tools\Util::readFile($dir.'/src/PHK/Stream/Backend.php');
 162  $this->code .= \PHK\Tools\Util::readFile($dir.'/src/PHK/Virtual/DC.php');
 163  $this->code .= \PHK\Tools\Util::readFile($dir.'/src/PHK/Virtual/Tree.php');
 164  $this->code .= \PHK\Tools\Util::readFile($dir.'/src/PHK/Virtual/Node.php');
 165  $this->code .= \PHK\Tools\Util::readFile($dir.'/src/PHK/Virtual/Dir.php');
 166  $this->code .= \PHK\Tools\Util::readFile($dir.'/src/PHK/Virtual/File.php');
 167  $this->code .= \PHK\Tools\Util::readFile($dir.'/src/PHK/Web/Info.php');
 168  $this->code .= \PHK\Tools\Util::readFile($dir.'/src/PHK/UnitTest/PHPUnit.php');
 169  
 170  $this->processPhpCode($this->code);
 171  
 172  $this->code=str_replace('<?php','',$this->code);
 173  $this->code=str_replace('?>','',$this->code);
 174  }
 175  
 176  //---------
 177  //-- Build prolog code
 178  //-- $dir= base dir where files are stored
 179  
 180  public function buildProlog($dir)
 181  {
 182  \Phool\Display::trace('Building prolog');
 183  
 184  $this->prolog = \PHK\Tools\Util::readFile($dir.'/scripts/prolog.php');
 185  
 186  //-- The four FF chars turn unicode detection off (see PHP bug #42396)
 187  
 188  $this->prolog .= '<?php __halt_compiler(); ?>'.str_repeat(chr(255),4);
 189  
 190  $this->processPhpCode($this->prolog);
 191  }
 192  
 193  //---------
 194  // Create a new section and fill it with some data
 195  
 196  public function addSection($name,$data,$modifiers=array())
 197  {
 198  \Phool\Display::trace("Adding section <$name>");
 199  
 200  $this->proxy()->stree()->mkfile($name,$data,$modifiers);
 201  }
 202  
 203  //---------
 204  
 205  public function dump($path=null)
 206  {
 207  if (is_null($path)) $path=$this->path();
 208  \Phool\Display::trace("Writing package to disk ($path)");
 209  
 210  $base_dir=dirname(dirname(dirname(__DIR__)));
 211  $this->buildPhpCode($base_dir);
 212  
 213  //-- Get creator version
 214  
 215  if (\PHK\Mgr::isPhkUri(__FILE__))
 216      {
 217      $pkg=\PHK\Mgr::instance(\PHK\Mgr::uriToMnt(__FILE__));
 218      $creatorVersion=$pkg->option('version');
 219      }
 220  else
 221      {
 222      $creatorVersion=getenv('SOFTWARE_VERSION');
 223      }
 224  if (!is_string($creatorVersion))
 225      throw new \Exception('Cannot determine creator version');
 226  
 227  //-- Build prolog if not already set
 228  
 229  if (is_null($this->prolog)) $this->buildProlog($base_dir);
 230  
 231  //-- Build FILES part and FTREE section
 232  // Build map, strip sources, etc...
 233  
 234  $needed_extensions=new \PHK\Tools\ItemLister;
 235  $this->proxy()->ftree()->walk('getNeededExtensions',$this,$needed_extensions);
 236  
 237  $map=new \Automap\Build\Creator();
 238  list($files_structure,$files_data)=$this->proxy()->ftree()->export($this,$map);
 239  
 240  $this->addSection('FTREE',$files_structure);
 241  unset($files_structure);
 242  
 243  //-- Build Automap section
 244  
 245  if ($map->symbolCount())
 246      $this->addSection(\PHK\Proxy::AUTOMAP_SECTION,$map->serialize());
 247  
 248  $this->updateBuildInfo('map_defined',($map->symbolCount()!=0));
 249  
 250  //-- Tabs sections / PHK icon
 251  
 252  foreach(array('tabs/left.gif','tabs/right.gif','tabs/bottom.gif'
 253      ,'tabs/tabs.css.php','phk_logo.png') as $f)
 254      {
 255      $source=$base_dir.'/etc/'.$f;
 256      $this->addSection('STATIC/'.$f,\PHK\Tools\Util::readFile($source));
 257      }
 258  
 259  //-- Build info
 260  
 261  $this->updateBuildInfo('phk_creator_version',$creatorVersion);
 262  $this->updateBuildInfo('automap_creator_version',\Automap\Build\Creator::VERSION);
 263  $this->updateBuildInfo('automap_minVersion',\Automap\Build\Creator::MIN_RUNTIME_VERSION);
 264  
 265  //-- Record the user-specified needed extensions
 266  
 267  foreach(\PHK\Tools\Util::mkArray($this->option('required_extensions')) as $ext)
 268      {
 269      if ($ext!=='') $needed_extensions->add($ext,true);
 270      }
 271  
 272  //-- Flush sections
 273  //-- Add the uncompress needed extensions to the user required extensions
 274  
 275  $this->proxy()->stree()->walk('getNeededExtensions',$this,$needed_extensions);
 276  
 277  $ext=array_keys($needed_extensions->get());
 278  if (count($ext)) $this->updateOption('required_extensions',$ext);
 279  
 280  //-- Ensure mime_types, if present, is an array
 281  
 282  if (!is_null($this->option('mime_types')))
 283      $this->updateOption('mime_types'
 284          ,\PHK\Tools\Util::mkArray($this->option('mime_types')));
 285  
 286  $this->addSection('OPTIONS',serialize($this->options()));
 287  
 288  // Add build info section
 289  
 290  $this->addSection('BUILD_INFO',serialize($this->buildInfo()));
 291  
 292  // Now, dump the section tree
 293  
 294  \PHK\Tools\Util::trace('--- Sections');
 295  
 296  list($sections_structure,$sections_data)=$this->proxy()->stree()->export($this);
 297  
 298  //---
 299  
 300  $prolog_offset=\PHK\Proxy::INTERP_LEN+\PHK\Proxy::MAGIC_LINE_LEN;
 301  $code_offset=$prolog_offset+strlen($this->prolog);
 302  $sections_structure_offset=$code_offset+strlen($this->code);
 303  $sections_offset=$sections_structure_offset+strlen($sections_structure);
 304  $files_offset=$sections_offset+strlen($sections_data);
 305  $sig_offset=$files_offset+strlen($files_data);
 306  $file_size=$sig_offset;
 307  
 308  $buf=\PHK\Proxy::fixCrc(\PHK\Proxy::interpBlock($this->interp)
 309      .'<?php '.\PHK\Proxy::MAGIC_STRING
 310      .' M'  .str_pad(self::MIN_RUNTIME_VERSION,\PHK\Proxy::VERSION_SIZE)
 311      .' V'  .str_pad($creatorVersion,\PHK\Proxy::VERSION_SIZE)
 312      .' FS' .str_pad($file_size,\PHK\Proxy::OFFSET_SIZE)
 313      .' PO' .str_pad($prolog_offset,\PHK\Proxy::OFFSET_SIZE)
 314      .' SSO'.str_pad($sections_structure_offset,\PHK\Proxy::OFFSET_SIZE)
 315      .' STO'.str_pad($sections_offset,\PHK\Proxy::OFFSET_SIZE)
 316      .' FTO'.str_pad($files_offset,\PHK\Proxy::OFFSET_SIZE)
 317      .' SIO'.str_pad($sig_offset,\PHK\Proxy::OFFSET_SIZE)
 318      .' CRC00000000'
 319      .' PCO'.str_pad($code_offset,\PHK\Proxy::OFFSET_SIZE)
 320      .' PCS'.str_pad(strlen($this->code),\PHK\Proxy::OFFSET_SIZE)
 321      .' ?>'
 322      .$this->prolog.$this->code.$sections_structure.$sections_data.$files_data);
 323  
 324  \PHK\Tools\Util::trace('Writing PHK file to '.$path);
 325  \PHK\Tools\Util::atomicWrite($path,$buf);
 326  }
 327  
 328  //---
 329  } // End of class
 330  //===========================================================================
 331  } // End of class_exists
 332  //===========================================================================
 333  } // End of namespace
 334  //===========================================================================
 335  ?>


Generated: Thu Jun 4 18:33:15 2015 Cross-referenced by PHPXref 0.7.1