| [ Index ] |
PHP Cross Reference of Akelos Framework |
[Summary view] [Print] [Text view]
1 <?php 2 3 4 defined('AK_CLASS_EXTENDER_ENABLE_CACHE') ? null : define('AK_CLASS_EXTENDER_ENABLE_CACHE', !AK_DEV_MODE); 5 /** 6 * @ WARNING too experimental. This is a proof of concept. Do not use it for production. 7 * 8 * The AkClassExtender provides the means for extending core Akelos Framework 9 * functionality by chaining multiple objects and creating an extended 10 * composite class of the original. 11 * 12 * It is a good practice maintaining the level of parents low when writing OO 13 * code, but PHP classes are closed and do not allow runtime modification so 14 * this method will allow others to write core extensions that modify the default 15 * Akelos Framework behavior. 16 * 17 * This technique requires that the participants of the class chain are not included yet 18 * during execution, ass participants code will be joined, modified and cached for 19 * including it as a single source file. 20 */ 21 class AkClassExtender 22 { 23 var $_extended_classes; 24 25 function extendClassWithSource($class_name_to_extend, $extension_path, $priority = 10) 26 { 27 $this->_extended_classes[$class_name_to_extend][$priority][] = $extension_path; 28 } 29 30 function _getExtensionFilePaths($class_name_to_extend) 31 { 32 $extension_files = array(); 33 if(!empty($this->_extended_classes[$class_name_to_extend])){ 34 $extensions = $this->_extended_classes[$class_name_to_extend]; 35 ksort($extensions); 36 foreach ($extensions as $files){ 37 $extension_files = array_merge($extension_files, $files); 38 } 39 } 40 return $extension_files; 41 } 42 43 function _getExtensionSourceAndChecksum($class_name_to_extend) 44 { 45 $file_contents = ''; 46 $file_paths = $this->_getExtensionFilePaths($class_name_to_extend); 47 $checksum = md5(serialize($file_paths)); 48 if(!$this->_canIncludeMergedFile($class_name_to_extend, $checksum)){ 49 foreach ($file_paths as $file_path){ 50 if(is_file($file_path)){ 51 $file_contents .= Ak::file_get_contents($file_path); 52 } 53 } 54 return array($checksum, $file_contents); 55 }else{ 56 return false; 57 } 58 } 59 60 function extendClasses() 61 { 62 foreach (array_keys($this->_extended_classes) as $class_name_to_extend){ 63 $this->makeClassExtensible($class_name_to_extend); 64 } 65 } 66 67 function makeClassExtensible($class_name_to_extend) 68 { 69 list($checksum, $source) = $this->_getExtensionSourceAndChecksum($class_name_to_extend); 70 $merge_path = AK_TMP_DIR.DS.'.lib'; 71 if($source){ 72 if(preg_match_all('/[ \n\t]*([a-z]+)[ \n\t]*extends[ \n\t]*('.$class_name_to_extend.')[ \n\t]*[ \n\t]*{/i', $source, $matches)){ 73 $replacements = array(); 74 $extended_by = array(); 75 76 foreach ($matches[2] as $k => $class_to_extend){ 77 if(empty($last_method) && class_exists($class_to_extend)){ 78 $last_method = $class_to_extend; 79 } 80 if($class_to_extend == $last_method || !empty($extended_by[$class_to_extend]) && in_array($last_method,$extended_by[$class_to_extend])){ 81 if(!class_exists($matches[1][$k])){ 82 $replacements[trim($matches[0][$k],"\n\t {")] = $matches[1][$k].' extends '.$last_method; 83 $last_method = $matches[1][$k]; 84 $extended_by[$class_to_extend][] = $last_method; 85 } else { 86 trigger_error(Ak::t('The class %class is already defined and can\'t be used for extending %parent_class', array('%class' => $matches[1][$k], '%parent_class' => $class_name_to_extend)), E_NOTICE); 87 } 88 } 89 } 90 $source = str_replace(array_keys($replacements), array_values($replacements), $source); 91 } 92 $source = "$source<?php class Extensible$class_name_to_extend extends $last_method{} ?>"; 93 if(md5($source) != @md5_file($merge_path.DS.'Extensible'.$class_name_to_extend.'.php')){ 94 Ak::file_put_contents($merge_path.DS.'Extensible'.$class_name_to_extend.'.php', $source); 95 Ak::file_put_contents($merge_path.DS.'checksums'.DS.'Extensible'.$class_name_to_extend, $checksum); 96 } 97 } 98 99 include_once($merge_path.DS.'Extensible'.$class_name_to_extend.'.php'); 100 } 101 102 function _canIncludeMergedFile($class_name_to_extend, $checksum) 103 { 104 $merge_path = AK_TMP_DIR.DS.'.lib'; 105 if(AK_CLASS_EXTENDER_ENABLE_CACHE && file_exists($merge_path.DS.'Extensible'.$class_name_to_extend.'.php') && 106 Ak::file_get_contents($merge_path.DS.'checksums'.DS.'Extensible'.$class_name_to_extend) == $checksum){ 107 return true; 108 } 109 return false; 110 } 111 } 112 113 114 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Oct 27 12:43:49 2008 | Cross-referenced by PHPXref 0.6 |