Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

1010 lines (857 sloc) 28.847 kb
/*
+----------------------------------------------------------------------+
| Yet Another Framework |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Xinchen Hui <laruence@php.net> |
+----------------------------------------------------------------------+
*/
/* $Id: yaf_loader.c 327580 2012-09-10 06:31:34Z laruence $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "main/SAPI.h"
#include "Zend/zend_alloc.h"
#include "ext/standard/php_smart_str.h"
#include "TSRM/tsrm_virtual_cwd.h"
#include "php_yaf.h"
#include "yaf_application.h"
#include "yaf_namespace.h"
#include "yaf_request.h"
#include "yaf_loader.h"
#include "yaf_exception.h"
zend_class_entry *yaf_loader_ce;
/** {{{ ARG_INFO
*/
ZEND_BEGIN_ARG_INFO_EX(yaf_loader_void_arginfo, 0, 0, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(yaf_loader_getinstance_arginfo, 0, 0, 0)
ZEND_ARG_INFO(0, local_library_path)
ZEND_ARG_INFO(0, global_library_path)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(yaf_loader_autoloader_arginfo, 0, 0, 1)
ZEND_ARG_INFO(0, class_name)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(yaf_loader_regnamespace_arginfo, 0, 0, 1)
ZEND_ARG_INFO(0, name_prefix)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(yaf_loader_islocalname_arginfo, 0, 0, 1)
ZEND_ARG_INFO(0, class_name)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(yaf_loader_import_arginfo, 0, 0, 1)
ZEND_ARG_INFO(0, file)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(yaf_loader_setlib_arginfo, 0, 0, 1)
ZEND_ARG_INFO(0, library_path)
ZEND_ARG_INFO(0, is_global)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(yaf_loader_getlib_arginfo, 0, 0, 0)
ZEND_ARG_INFO(0, is_global)
ZEND_END_ARG_INFO()
/* }}} */
/** {{{ int yaf_loader_register(TSRMLS_D)
*/
int yaf_loader_register(yaf_loader_t *loader TSRMLS_DC) {
zval *autoload, *method, *function, *ret = NULL;
zval **params[1] = {&autoload};
MAKE_STD_ZVAL(autoload);
array_init(autoload);
MAKE_STD_ZVAL(method);
ZVAL_STRING(method, YAF_AUTOLOAD_FUNC_NAME, 1);
zend_hash_next_index_insert(Z_ARRVAL_P(autoload), &loader, sizeof(yaf_loader_t *), NULL);
zend_hash_next_index_insert(Z_ARRVAL_P(autoload), &method, sizeof(zval *), NULL);
MAKE_STD_ZVAL(function);
ZVAL_STRING(function, YAF_SPL_AUTOLOAD_REGISTER_NAME, 0);
do {
zend_fcall_info fci = {
sizeof(fci),
EG(function_table),
function,
NULL,
&ret,
1,
(zval ***)params,
NULL,
1
};
if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE) {
if (ret) {
zval_ptr_dtor(&ret);
}
efree(function);
zval_ptr_dtor(&autoload);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to register autoload function %s", YAF_AUTOLOAD_FUNC_NAME);
return 0;
}
/*{{{ no use anymore
if (0 && !YAF_G(use_spl_autoload)) {
zend_function *reg_function;
zend_internal_function override_function = {
ZEND_INTERNAL_FUNCTION,
YAF_AUTOLOAD_FUNC_NAME,
NULL,
ZEND_ACC_PUBLIC,
NULL,
1,
0,
NULL,
0,
0,
ZEND_FN(yaf_override_spl_autoload),
NULL
};
zend_internal_function *internal_function = (zend_internal_function *)&override_function;
internal_function->type = ZEND_INTERNAL_FUNCTION;
internal_function->module = NULL;
internal_function->handler = ZEND_FN(yaf_override_spl_autoload);
internal_function->function_name = YAF_AUTOLOAD_FUNC_NAME;
internal_function->scope = NULL;
internal_function->prototype = NULL;
internal_function->arg_info = NULL;
internal_function->num_args = 1;
internal_function->required_num_args = 0;
internal_function->pass_rest_by_reference = 0;
internal_function->return_reference = 0;
internal_function->fn_flags = ZEND_ACC_PUBLIC;
function_add_ref((zend_function*)&override_function);
//zend_register_functions
if (zend_hash_update(EG(function_table), YAF_SPL_AUTOLOAD_REGISTER_NAME,
sizeof(YAF_SPL_AUTOLOAD_REGISTER_NAME), &override_function, sizeof(zend_function), (void **)&reg_function) == FAILURE) {
YAF_DEBUG("register autoload failed");
//no big deal
}
}
}}} */
if (ret) {
zval_ptr_dtor(&ret);
}
efree(function);
zval_ptr_dtor(&autoload);
} while (0);
return 1;
}
/* }}} */
/** {{{ static int yaf_loader_is_category(char *class, uint class_len, char *category, uint category_len TSRMLS_DC)
*/
static int yaf_loader_is_category(char *class, uint class_len, char *category, uint category_len TSRMLS_DC) {
uint separator_len = YAF_G(name_separator_len);
if (YAF_G(name_suffix)) {
if (class_len > category_len && strncmp(class + class_len - category_len, category, category_len) == 0) {
if (!separator_len || strncmp(class + class_len - category_len - separator_len, YAF_G(name_separator), separator_len) == 0) {
return 1;
}
}
} else {
if (strncmp(class, category, category_len) == 0) {
if (!separator_len || strncmp(class + category_len, YAF_G(name_separator), separator_len) == 0) {
return 1;
}
}
}
return 0;
}
/* }}} */
/** {{{ int yaf_loader_is_local_namespace(yaf_loader_t *loader, char *class_name, int len TSRMLS_DC)
*/
int yaf_loader_is_local_namespace(yaf_loader_t *loader, char *class_name, int len TSRMLS_DC) {
char *pos, *ns, *prefix = NULL;
char orig_char, *backup = NULL;
uint prefix_len = 0;
if (!YAF_G(local_namespaces)) {
return 0;
}
ns = YAF_G(local_namespaces);
pos = strstr(class_name, "_");
if (pos) {
prefix_len = pos - class_name;
prefix = class_name;
backup = class_name + prefix_len;
orig_char = '_';
*backup = '\0';
}
#ifdef YAF_HAVE_NAMESPACE
else if ((pos = strstr(class_name, "\\"))) {
prefix_len = pos - class_name;
prefix = estrndup(class_name, prefix_len);
orig_char = '\\';
backup = class_name + prefix_len;
*backup = '\0';
}
#endif
else {
prefix = class_name;
prefix_len = len;
}
if (!prefix) {
return 0;
}
while ((pos = strstr(ns, prefix))) {
if ((pos == ns) && (*(pos + prefix_len) == DEFAULT_DIR_SEPARATOR || *(pos + prefix_len) == '\0')) {
if (backup) {
*backup = orig_char;
}
return 1;
} else if (*(pos - 1) == DEFAULT_DIR_SEPARATOR
&& (*(pos + prefix_len) == DEFAULT_DIR_SEPARATOR || *(pos + prefix_len) == '\0')) {
if (backup) {
*backup = orig_char;
}
return 1;
}
ns = pos + prefix_len;
}
if (backup) {
*backup = orig_char;
}
return 0;
}
/* }}} */
/** {{{ yaf_loader_t * yaf_loader_instance(yaf_loader_t *this_ptr, char *library_path, char *global_path TSRMLS_DC)
*/
yaf_loader_t * yaf_loader_instance(yaf_loader_t *this_ptr, char *library_path, char *global_path TSRMLS_DC) {
yaf_loader_t *instance;
zval *glibrary, *library;
instance = zend_read_static_property(yaf_loader_ce, ZEND_STRL(YAF_LOADER_PROPERTY_NAME_INSTANCE), 1 TSRMLS_CC);
if (IS_OBJECT == Z_TYPE_P(instance)) {
/* unecessary since there is no set_router things
&& instanceof_function(Z_OBJCE_P(instance), yaf_loader_ce TSRMLS_CC)) {
*/
if (library_path) {
MAKE_STD_ZVAL(library);
ZVAL_STRING(library, library_path, 1);
zend_update_property(yaf_loader_ce, instance, ZEND_STRL(YAF_LOADER_PROPERTY_NAME_LIBRARY), library TSRMLS_CC);
zval_ptr_dtor(&library);
}
if (global_path) {
MAKE_STD_ZVAL(glibrary);
ZVAL_STRING(glibrary, global_path, 1);
zend_update_property(yaf_loader_ce, instance, ZEND_STRL(YAF_LOADER_PROPERTY_NAME_GLOBAL_LIB), glibrary TSRMLS_CC);
zval_ptr_dtor(&glibrary);
}
return instance;
}
if (!global_path && !library_path) {
return NULL;
}
if (this_ptr) {
instance = this_ptr;
} else {
MAKE_STD_ZVAL(instance);
object_init_ex(instance, yaf_loader_ce);
}
if (library_path && global_path) {
MAKE_STD_ZVAL(glibrary);
MAKE_STD_ZVAL(library);
ZVAL_STRING(glibrary, global_path, 1);
ZVAL_STRING(library, library_path, 1);
zend_update_property(yaf_loader_ce, instance, ZEND_STRL(YAF_LOADER_PROPERTY_NAME_LIBRARY), library TSRMLS_CC);
zend_update_property(yaf_loader_ce, instance, ZEND_STRL(YAF_LOADER_PROPERTY_NAME_GLOBAL_LIB), glibrary TSRMLS_CC);
zval_ptr_dtor(&library);
zval_ptr_dtor(&glibrary);
} else if (!global_path) {
MAKE_STD_ZVAL(library);
ZVAL_STRING(library, library_path, 1);
zend_update_property(yaf_loader_ce, instance, ZEND_STRL(YAF_LOADER_PROPERTY_NAME_LIBRARY), library TSRMLS_CC);
zend_update_property(yaf_loader_ce, instance, ZEND_STRL(YAF_LOADER_PROPERTY_NAME_GLOBAL_LIB), library TSRMLS_CC);
zval_ptr_dtor(&library);
} else {
MAKE_STD_ZVAL(glibrary);
ZVAL_STRING(glibrary, global_path, 1);
zend_update_property(yaf_loader_ce, instance, ZEND_STRL(YAF_LOADER_PROPERTY_NAME_LIBRARY), glibrary TSRMLS_CC);
zend_update_property(yaf_loader_ce, instance, ZEND_STRL(YAF_LOADER_PROPERTY_NAME_GLOBAL_LIB), glibrary TSRMLS_CC);
zval_ptr_dtor(&glibrary);
}
if (!yaf_loader_register(instance TSRMLS_CC)) {
return NULL;
}
zend_update_static_property(yaf_loader_ce, ZEND_STRL(YAF_LOADER_PROPERTY_NAME_INSTANCE), instance TSRMLS_CC);
return instance;
}
/* }}} */
/** {{{ static void yaf_suppress_include_warning(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args)
*/
static void (*zend_origin_error_handler)(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args);
static void yaf_suppress_include_warning(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args) {
TSRMLS_FETCH();
if (YAF_G(suppressing_warning) && error_num == E_WARNING) {
char buffer[1024];
int buffer_len;
va_list copy;
/* va_copy() is __va_copy() in old gcc versions.
* According to the autoconf manual, using
* memcpy(&dst, &src, sizeof(va_list))
* gives maximum portability. */
#ifndef va_copy
# ifdef __va_copy
# define va_copy(dest, src) __va_copy((dest), (src))
# else
# define va_copy(dest, src) memcpy(&(dest), &(src), sizeof(va_list))
# endif
#endif
va_copy(copy, args);
buffer_len = vsnprintf(buffer, sizeof(buffer), format, copy);
#ifdef va_copy
va_end(copy);
#endif
if (strstr(buffer, "failed to open stream: ") != NULL) {
return;
}
if (strstr(buffer, "Failed opening ") != NULL) {
return;
}
}
return zend_origin_error_handler(error_num, error_filename, error_lineno, format, args);
}
/* }}} */
/** {{{ int yaf_loader_import(char *path, int len, int use_path TSRMLS_DC)
*/
int yaf_loader_import(char *path, int len, int use_path TSRMLS_DC) {
zend_file_handle file_handle;
zend_op_array *op_array;
zend_bool restore_cb = 0;
file_handle.filename = path;
file_handle.free_filename = 0;
file_handle.type = ZEND_HANDLE_FILENAME;
file_handle.opened_path = NULL;
file_handle.handle.fp = NULL;
if (!zend_origin_error_handler) {
restore_cb = 1;
zend_origin_error_handler = zend_error_cb;
zend_error_cb = yaf_suppress_include_warning;
YAF_G(suppressing_warning) = 1;
}
zend_try {
op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
} zend_catch {
if (restore_cb) {
YAF_G(suppressing_warning) = 0;
zend_error_cb = zend_origin_error_handler;
zend_origin_error_handler = NULL;
}
zend_bailout();
} zend_end_try();
if (restore_cb) {
YAF_G(suppressing_warning) = 0;
zend_error_cb = zend_origin_error_handler;
zend_origin_error_handler = NULL;
}
if (op_array && file_handle.handle.stream.handle) {
int dummy = 1;
if (!file_handle.opened_path) {
file_handle.opened_path = path;
}
zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL);
}
zend_destroy_file_handle(&file_handle TSRMLS_CC);
if (op_array) {
zval *result = NULL;
YAF_STORE_EG_ENVIRON();
EG(return_value_ptr_ptr) = &result;
EG(active_op_array) = op_array;
#if ((PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION > 2)) || (PHP_MAJOR_VERSION > 5)
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
}
#endif
zend_execute(op_array TSRMLS_CC);
destroy_op_array(op_array TSRMLS_CC);
efree(op_array);
if (!EG(exception)) {
if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
}
YAF_RESTORE_EG_ENVIRON();
return 1;
}
return 0;
}
/* }}} */
/** {{{ int yaf_internal_autoload(char * file_name, uint name_len, char **directory TSRMLS_DC)
*/
int yaf_internal_autoload(char *file_name, uint name_len, char **directory TSRMLS_DC) {
zval *library_dir, *global_dir;
char *q, *p, *seg;
uint seg_len, directory_len, status;
char *ext = YAF_G(ext);
smart_str buf = {0};
if (NULL == *directory) {
char *library_path;
uint library_path_len;
yaf_loader_t *loader;
loader = yaf_loader_instance(NULL, NULL, NULL TSRMLS_CC);
if (!loader) {
/* since only call from userspace can cause loader is NULL, exception throw will works well */
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s need to be initialize first", yaf_loader_ce->name);
return 0;
} else {
library_dir = zend_read_property(yaf_loader_ce, loader, ZEND_STRL(YAF_LOADER_PROPERTY_NAME_LIBRARY), 1 TSRMLS_CC);
global_dir = zend_read_property(yaf_loader_ce, loader, ZEND_STRL(YAF_LOADER_PROPERTY_NAME_GLOBAL_LIB), 1 TSRMLS_CC);
if (yaf_loader_is_local_namespace(loader, file_name, name_len TSRMLS_CC)) {
library_path = Z_STRVAL_P(library_dir);
library_path_len = Z_STRLEN_P(library_dir);
} else {
library_path = Z_STRVAL_P(global_dir);
library_path_len = Z_STRLEN_P(global_dir);
}
}
if (NULL == library_path) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s requires %s(which set the library_directory) to be initialized first", yaf_loader_ce->name, yaf_application_ce->name);
return 0;
}
smart_str_appendl(&buf, library_path, library_path_len);
} else {
smart_str_appendl(&buf, *directory, strlen(*directory));
efree(*directory);
}
directory_len = buf.len;
/* aussume all the path is not end in slash */
smart_str_appendc(&buf, DEFAULT_SLASH);
p = file_name;
q = p;
while (1) {
while(++q && *q != '_' && *q != '\0');
if (*q != '\0') {
seg_len = q - p;
seg = estrndup(p, seg_len);
smart_str_appendl(&buf, seg, seg_len);
efree(seg);
smart_str_appendc(&buf, DEFAULT_SLASH);
p = q + 1;
} else {
break;
}
}
if (YAF_G(lowcase_path)) {
/* all path of library is lowercase */
zend_str_tolower(buf.c + directory_len, buf.len - directory_len);
}
smart_str_appendl(&buf, p, strlen(p));
smart_str_appendc(&buf, '.');
smart_str_appendl(&buf, ext, strlen(ext));
smart_str_0(&buf);
if (directory) {
*(directory) = estrndup(buf.c, buf.len);
}
status = yaf_loader_import(buf.c, buf.len, 0 TSRMLS_CC);
smart_str_free(&buf);
if (!status)
return 0;
return 1;
}
/* }}} */
/** {{{ int yaf_loader_register_namespace_single(char *prefix, uint len TSRMLS_DC)
*/
int yaf_loader_register_namespace_single(char *prefix, uint len TSRMLS_DC) {
char *namespaces;
if (YAF_G(local_namespaces)) {
uint orig_len = strlen(YAF_G(local_namespaces));
YAF_G(local_namespaces) = erealloc(YAF_G(local_namespaces), orig_len + 1 + len + 1);
snprintf(YAF_G(local_namespaces) + orig_len, len + 2, "%c%s", DEFAULT_DIR_SEPARATOR, prefix);
} else {
namespaces = YAF_G(local_namespaces) = emalloc(len + 1 + 1);
snprintf(YAF_G(local_namespaces), len + 2, "%s", prefix);
}
return 1;
}
/* }}} */
/** {{{ int yaf_loader_register_namespace_multi(zval *prefixes TSRMLS_DC)
*/
int yaf_loader_register_namespace_multi(zval *prefixes TSRMLS_DC) {
zval **ppzval;
HashTable *ht;
ht = Z_ARRVAL_P(prefixes);
for(zend_hash_internal_pointer_reset(ht);
zend_hash_has_more_elements(ht) == SUCCESS;
zend_hash_move_forward(ht)) {
if (zend_hash_get_current_data(ht, (void**)&ppzval) == FAILURE) {
continue;
} else if (IS_STRING == Z_TYPE_PP(ppzval)) {
yaf_loader_register_namespace_single(Z_STRVAL_PP(ppzval), Z_STRLEN_PP(ppzval) TSRMLS_CC);
}
}
return 1;
}
/* }}} */
/** {{{ proto private Yaf_Loader::__construct(void)
*/
PHP_METHOD(yaf_loader, __construct) {
}
/* }}} */
/** {{{ proto private Yaf_Loader::__sleep(void)
*/
PHP_METHOD(yaf_loader, __sleep) {
}
/* }}} */
/** {{{ proto private Yaf_Loader::__wakeup(void)
*/
PHP_METHOD(yaf_loader, __wakeup) {
}
/* }}} */
/** {{{ proto private Yaf_Loader::__clone(void)
*/
PHP_METHOD(yaf_loader, __clone) {
}
/* }}} */
/** {{{ proto public Yaf_Loader::registerLocalNamespace(mixed $namespace)
*/
PHP_METHOD(yaf_loader, registerLocalNamespace) {
zval *namespaces;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &namespaces) == FAILURE) {
return;
}
if (IS_STRING == Z_TYPE_P(namespaces)) {
if (yaf_loader_register_namespace_single(Z_STRVAL_P(namespaces), Z_STRLEN_P(namespaces) TSRMLS_CC)) {
RETURN_ZVAL(getThis(), 1, 0);
}
} else if (IS_ARRAY == Z_TYPE_P(namespaces)) {
if(yaf_loader_register_namespace_multi(namespaces TSRMLS_CC)) {
RETURN_ZVAL(getThis(), 1, 0);
}
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parameters provided, must be a string, or an array");
}
RETURN_FALSE;
}
/* }}} */
/** {{{ proto public Yaf_Loader::getLocalNamespace(void)
*/
PHP_METHOD(yaf_loader, getLocalNamespace) {
if (YAF_G(local_namespaces)) {
RETURN_STRING(YAF_G(local_namespaces), 1);
}
RETURN_NULL();
}
/* }}} */
/** {{{ proto public Yaf_Loader::clearLocalNamespace(void)
*/
PHP_METHOD(yaf_loader, clearLocalNamespace) {
efree(YAF_G(local_namespaces));
YAF_G(local_namespaces) = NULL;
RETURN_TRUE;
}
/* }}} */
/** {{{ proto public Yaf_Loader::isLocalName(string $class_name)
*/
PHP_METHOD(yaf_loader, isLocalName) {
zval *name;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &name) == FAILURE) {
return;
}
if (Z_TYPE_P(name) != IS_STRING) {
RETURN_FALSE;
}
RETURN_BOOL(yaf_loader_is_local_namespace(getThis(), Z_STRVAL_P(name), Z_STRLEN_P(name) TSRMLS_CC));
}
/* }}} */
/** {{{ proto public Yaf_Loader::setLibraryPath(string $path, $global = FALSE)
*/
PHP_METHOD(yaf_loader, setLibraryPath) {
char *library;
uint len;
zend_bool global = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &library, &len, &global) == FAILURE) {
return;
}
if (!global) {
zend_update_property_stringl(yaf_loader_ce, getThis(), ZEND_STRL(YAF_LOADER_PROPERTY_NAME_LIBRARY), library, len TSRMLS_CC);
} else {
zend_update_property_stringl(yaf_loader_ce, getThis(), ZEND_STRL(YAF_LOADER_PROPERTY_NAME_GLOBAL_LIB), library, len TSRMLS_CC);
}
RETURN_ZVAL(getThis(), 1, 0);
}
/* }}} */
/** {{{ proto public Yaf_Loader::getLibraryPath($global = FALSE)
*/
PHP_METHOD(yaf_loader, getLibraryPath) {
zval *library;
zend_bool global = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &global) == FAILURE) {
return;
}
if (!global) {
library = zend_read_property(yaf_loader_ce, getThis(), ZEND_STRL(YAF_LOADER_PROPERTY_NAME_LIBRARY), 1 TSRMLS_CC);
} else {
library = zend_read_property(yaf_loader_ce, getThis(), ZEND_STRL(YAF_LOADER_PROPERTY_NAME_GLOBAL_LIB), 1 TSRMLS_CC);
}
RETURN_ZVAL(library, 1, 0);
}
/* }}} */
/** {{{ proto public static Yaf_Loader::import($file)
*/
PHP_METHOD(yaf_loader, import) {
char *file;
uint len, need_free = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s" ,&file, &len) == FAILURE) {
return;
}
if (!len) {
RETURN_FALSE;
} else {
int retval = 0;
if (!IS_ABSOLUTE_PATH(file, len)) {
yaf_loader_t *loader = yaf_loader_instance(NULL, NULL, NULL TSRMLS_CC);
if (!loader) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s need to be initialize first", yaf_loader_ce->name);
RETURN_FALSE;
} else {
zval *library = zend_read_property(yaf_loader_ce, loader, ZEND_STRL(YAF_LOADER_PROPERTY_NAME_LIBRARY), 1 TSRMLS_CC);
len = spprintf(&file, 0, "%s%c%s", Z_STRVAL_P(library), DEFAULT_SLASH, file);
need_free = 1;
}
}
retval = (zend_hash_exists(&EG(included_files), file, len + 1));
if (retval) {
if (need_free) {
efree(file);
}
RETURN_TRUE;
}
retval = yaf_loader_import(file, len, 0 TSRMLS_CC);
if (need_free) {
efree(file);
}
RETURN_BOOL(retval);
}
}
/* }}} */
/** {{{ proto public Yaf_Loader::autoload($class_name)
*/
PHP_METHOD(yaf_loader, autoload) {
char *class_name, *origin_classname, *app_directory, *directory = NULL, *file_name = NULL;
#ifdef YAF_HAVE_NAMESPACE
char *origin_lcname = NULL;
#endif
uint separator_len, class_name_len, file_name_len = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &class_name, &class_name_len) == FAILURE) {
return;
}
separator_len = YAF_G(name_separator_len);
app_directory = YAF_G(directory);
origin_classname = class_name;
do {
if (!class_name_len) {
break;
}
#ifdef YAF_HAVE_NAMESPACE
{
int pos = 0;
origin_lcname = estrndup(class_name, class_name_len);
class_name = origin_lcname;
while (pos < class_name_len) {
if (*(class_name + pos) == '\\') {
*(class_name + pos) = '_';
}
pos += 1;
}
}
#endif
if (strncmp(class_name, YAF_LOADER_RESERVERD, YAF_LOADER_LEN_RESERVERD) == 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "You should not use '%s' as class name prefix", YAF_LOADER_RESERVERD);
}
if (yaf_loader_is_category(class_name, class_name_len, YAF_LOADER_MODEL, YAF_LOADER_LEN_MODEL TSRMLS_CC)) {
/* this is a model class */
spprintf(&directory, 0, "%s/%s", app_directory, YAF_MODEL_DIRECTORY_NAME);
file_name_len = class_name_len - separator_len - YAF_LOADER_LEN_MODEL;
if (YAF_G(name_suffix)) {
file_name = estrndup(class_name, file_name_len);
} else {
file_name = estrdup(class_name + YAF_LOADER_LEN_MODEL + separator_len);
}
break;
}
if (yaf_loader_is_category(class_name, class_name_len, YAF_LOADER_PLUGIN, YAF_LOADER_LEN_PLUGIN TSRMLS_CC)) {
/* this is a plugin class */
spprintf(&directory, 0, "%s/%s", app_directory, YAF_PLUGIN_DIRECTORY_NAME);
file_name_len = class_name_len - separator_len - YAF_LOADER_LEN_PLUGIN;
if (YAF_G(name_suffix)) {
file_name = estrndup(class_name, file_name_len);
} else {
file_name = estrdup(class_name + YAF_LOADER_LEN_PLUGIN + separator_len);
}
break;
}
if (yaf_loader_is_category(class_name, class_name_len, YAF_LOADER_CONTROLLER, YAF_LOADER_LEN_CONTROLLER TSRMLS_CC)) {
/* this is a controller class */
spprintf(&directory, 0, "%s/%s", app_directory, YAF_CONTROLLER_DIRECTORY_NAME);
file_name_len = class_name_len - separator_len - YAF_LOADER_LEN_CONTROLLER;
if (YAF_G(name_suffix)) {
file_name = estrndup(class_name, file_name_len);
} else {
file_name = estrdup(class_name + YAF_LOADER_LEN_CONTROLLER + separator_len);
}
break;
}
/* {{{ This only effects internally */
if (YAF_G(st_compatible) && (strncmp(class_name, YAF_LOADER_DAO, YAF_LOADER_LEN_DAO) == 0
|| strncmp(class_name, YAF_LOADER_SERVICE, YAF_LOADER_LEN_SERVICE) == 0)) {
/* this is a model class */
spprintf(&directory, 0, "%s/%s", app_directory, YAF_MODEL_DIRECTORY_NAME);
}
/* }}} */
file_name_len = class_name_len;
file_name = class_name;
} while(0);
if (!app_directory && directory) {
efree(directory);
#ifdef YAF_HAVE_NAMESPACE
if (origin_lcname) {
efree(origin_lcname);
}
#endif
if (file_name != class_name) {
efree(file_name);
}
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Couldn't load a framework MVC class without an %s initializing", yaf_application_ce->name);
RETURN_FALSE;
}
if (!YAF_G(use_spl_autoload)) {
/** directory might be NULL since we passed a NULL */
if (yaf_internal_autoload(file_name, file_name_len, &directory TSRMLS_CC)) {
char *lc_classname = zend_str_tolower_dup(origin_classname, class_name_len);
if (zend_hash_exists(EG(class_table), lc_classname, class_name_len + 1)) {
#ifdef YAF_HAVE_NAMESPACE
if (origin_lcname) {
efree(origin_lcname);
}
#endif
if (directory) {
efree(directory);
}
if (file_name != class_name) {
efree(file_name);
}
efree(lc_classname);
RETURN_TRUE;
} else {
efree(lc_classname);
php_error_docref(NULL TSRMLS_CC, E_STRICT, "Could not find class %s in %s", class_name, directory);
}
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find script %s", directory);
}
#ifdef YAF_HAVE_NAMESPACE
if (origin_lcname) {
efree(origin_lcname);
}
#endif
if (directory) {
efree(directory);
}
if (file_name != class_name) {
efree(file_name);
}
RETURN_TRUE;
} else {
char *lower_case_name = zend_str_tolower_dup(origin_classname, class_name_len);
if (yaf_internal_autoload(file_name, file_name_len, &directory TSRMLS_CC) &&
zend_hash_exists(EG(class_table), lower_case_name, class_name_len + 1)) {
#ifdef YAF_HAVE_NAMESPACE
if (origin_lcname) {
efree(origin_lcname);
}
#endif
if (directory) {
efree(directory);
}
if (file_name != class_name) {
efree(file_name);
}
efree(lower_case_name);
RETURN_TRUE;
}
#ifdef YAF_HAVE_NAMESPACE
if (origin_lcname) {
efree(origin_lcname);
}
#endif
if (directory) {
efree(directory);
}
if (file_name != class_name) {
efree(file_name);
}
efree(lower_case_name);
RETURN_FALSE;
}
}
/* }}} */
/** {{{ proto public Yaf_Loader::getInstance($library = NULL, $global_library = NULL)
*/
PHP_METHOD(yaf_loader, getInstance) {
char *library = NULL;
char *global = NULL;
int library_len = 0;
int global_len = 0;
yaf_loader_t *loader;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ss", &library, &library_len, &global, &global_len) == FAILURE) {
return;
}
loader = yaf_loader_instance(NULL, library, global TSRMLS_CC);
if (loader)
RETURN_ZVAL(loader, 1, 0);
RETURN_FALSE;
}
/* }}} */
/** {{{ proto private Yaf_Loader::__desctruct(void)
*/
PHP_METHOD(yaf_loader, __destruct) {
}
/* }}} */
/** {{{ proto yaf_override_spl_autoload($class_name)
*/
PHP_FUNCTION(yaf_override_spl_autoload) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s is disabled by ap.use_spl_autoload", YAF_SPL_AUTOLOAD_REGISTER_NAME);
RETURN_BOOL(0);
}
/* }}} */
/** {{{ yaf_loader_methods
*/
zend_function_entry yaf_loader_methods[] = {
PHP_ME(yaf_loader, __construct, yaf_loader_void_arginfo, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR)
PHP_ME(yaf_loader, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_CLONE)
PHP_ME(yaf_loader, __sleep, NULL, ZEND_ACC_PRIVATE)
PHP_ME(yaf_loader, __wakeup, NULL, ZEND_ACC_PRIVATE)
PHP_ME(yaf_loader, autoload, yaf_loader_autoloader_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(yaf_loader, getInstance, yaf_loader_getinstance_arginfo, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(yaf_loader, registerLocalNamespace, yaf_loader_regnamespace_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(yaf_loader, getLocalNamespace, yaf_loader_void_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(yaf_loader, clearLocalNamespace, yaf_loader_void_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(yaf_loader, isLocalName, yaf_loader_islocalname_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(yaf_loader, import, yaf_loader_import_arginfo, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(yaf_loader, setLibraryPath, yaf_loader_setlib_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(yaf_loader, getLibraryPath, yaf_loader_getlib_arginfo, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
/* }}} */
/** {{{ YAF_STARTUP_FUNCTION
*/
YAF_STARTUP_FUNCTION(loader) {
zend_class_entry ce;
YAF_INIT_CLASS_ENTRY(ce, "Yaf_Loader", "Yaf\\Loader", yaf_loader_methods);
yaf_loader_ce = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
yaf_loader_ce->ce_flags |= ZEND_ACC_FINAL_CLASS;
zend_declare_property_null(yaf_loader_ce, ZEND_STRL(YAF_LOADER_PROPERTY_NAME_LIBRARY), ZEND_ACC_PROTECTED TSRMLS_CC);
zend_declare_property_null(yaf_loader_ce, ZEND_STRL(YAF_LOADER_PROPERTY_NAME_GLOBAL_LIB), ZEND_ACC_PROTECTED TSRMLS_CC);
zend_declare_property_null(yaf_loader_ce, ZEND_STRL(YAF_LOADER_PROPERTY_NAME_INSTANCE), ZEND_ACC_PROTECTED|ZEND_ACC_STATIC TSRMLS_CC);
return SUCCESS;
}
/* }}} */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/
Jump to Line
Something went wrong with that request. Please try again.