/** * * Setup; runs before each test method. * */ public function setup() { $this->_sql = Solar::factory('Solar_Sql', array('adapter' => 'Solar_Sql_Adapter_Sqlite', 'name' => ':memory:')); // forcibly add sql to registry Solar_Registry::set('sql', $this->_sql); $cmd = "CREATE TABLE acl (" . " flag VARCHAR(10)," . " type CHAR(100)," . " name VARCHAR(255)," . " class_name VARCHAR(255)," . " action_name VARCHAR(255)," . " position VARCHAR(255)" . ")"; $this->_sql->query($cmd); $dir = Solar_Class::dir('Test_Solar_Access_Adapter', '_support'); $lines = file_get_contents($dir . 'access.txt'); $rows = explode("\n", $lines); $pos = 0; foreach ($rows as $row) { $row = trim($row); // skip empty lines and comments if (empty($row) || substr($row, 0, 1) == '#') { continue; } $row = preg_replace('/[ \\t]{2,}/', ' ', $row); $row = explode(' ', $row); $data['flag'] = trim($row[0]); $data['type'] = trim($row[1]); $data['name'] = trim($row[2]); $data['class_name'] = trim($row[3]); $data['action_name'] = trim($row[4]); $data['position'] = $pos; $this->_sql->insert('acl', $data); $pos++; } parent::setup(); }
/** * * Test -- Fetches config file values. * */ public function testFetch() { $file = Solar_Class::dir('Mock_Solar_Config') . 'fetch.php'; $actual = Solar_Config::fetch($file); $expect = array('foo' => 'bar', 'baz' => 'sub', 'zim' => 'gir'); $this->assertSame($actual, $expect); }
protected function _preConfig() { parent::_preConfig(); $dir = Solar_Class::dir('Mock_Solar_Access_Adapter'); $file = $dir . 'access.txt'; $this->_Test_Solar_Access_Adapter_File['file'] = $file; }
protected function _preConfig() { parent::_preConfig(); $dir = Solar_Class::dir('Mock_Solar_Auth_Adapter_Htpasswd'); $file = $dir . 'users.htpasswd'; $this->_Test_Solar_Auth_Adapter_Htpasswd['file'] = $file; }
/** * _postConstruct * * @param $model */ protected function _postConstruct() { parent::_postConstruct(); $this->_model = $this->_config['model']; $this->_view_path = Solar_Class::dir($this, 'View'); $this->_view_file = 'index.php'; $this->_view = Solar::factory('Solar_View', array('template_path' => $this->_view_path)); }
public function testCallbacks_instanceMethod() { $file = Solar_Class::dir('Mock_Solar') . 'callbacks-instance-method.php'; Solar_File::load($file); $instance = Solar::factory('Solar_Callbacks_Instance_Method'); Solar::callbacks(array(array($instance, 'callback'))); $this->assertTrue($GLOBALS['SOLAR_CALLBACKS_INSTANCE_METHOD']); }
/** * _postConstruct * * @param $model */ protected function _postConstruct() { parent::_postConstruct(); $this->_model = $this->_config['model']; $this->_view_path = Solar_Class::dir($this, 'View'); $this->_view_file = 'index.php'; $this->_view = Solar::factory('Solar_View', array('template_path' => $this->_view_path)); $this->register = array('_preRender' => array('index' => array('main' => 'preRender')), '_postRender' => array('index' => array('main' => 'postRender')), '_preRun' => array('index' => array('main' => 'preRun')), '_postRun' => array('index' => array('main' => 'postRun')), '_postAction' => array('index' => array('main' => 'postAction'))); }
/** * * Test -- Sets the base directory for the class map. * */ public function testSetBase() { $dir = Solar_Class::dir('Solar', '..'); $base = Solar_Dir::fix(realpath($dir)); $map = Solar::factory('Solar_Class_Map'); $map->setBase($base); $actual = $map->getBase(); $this->assertSame($actual, $base); }
public function setup() { $dir = Solar_Class::dir('Test_Solar_Auth_Adapter', '_support'); $this->_config['file'] = $dir . 'users.ini'; $this->_moniker = 'Paul M. Jones'; $this->_email = '*****@*****.**'; $this->_uri = 'http://paul-m-jones.com'; parent::setup(); }
public function testIsValid_failures() { $checker = Solar::factory('Solar_Json_Checker'); $dir = Solar_Class::dir('Mock_Solar_Json'); $tests = scandir($dir); natsort($tests); foreach ($tests as $file) { if (substr($file, 0, 4) == 'fail' && substr($file, -4) == 'json') { $this->diag($file); $before = file_get_contents($dir . $file); $this->assertFalse($checker->isValid($before)); } } }
public function preTest() { parent::preTest(); // create the table $cmd = "CREATE TABLE {$this->_config['table']} (\n {$this->_config['handle_col']} VARCHAR(255),\n {$this->_config['role_col']} CHAR(32)\n )"; $this->_sql->query($cmd); // get the roles $dir = Solar_Class::dir('Mock_Solar_Role_Adapter_Sql'); $file = $dir . 'roles.ini'; $roles = parse_ini_file($file, true); // insert the roles foreach ($roles as $role => $val) { $handles = explode(',', $val['handles']); foreach ($handles as $handle) { $data[$this->_config['handle_col']] = trim($handle); $data[$this->_config['role_col']] = trim($role); $this->_sql->insert('roles', $data); } } }
public function setup() { $this->_sql = Solar::factory('Solar_Sql', array('adapter' => 'Solar_Sql_Adapter_Sqlite', 'name' => ':memory:')); $cmd = "CREATE TABLE members (" . " handle VARCHAR(255)," . " passwd CHAR(32)," . " email VARCHAR(255)," . " moniker VARCHAR(255)," . " uri VARCHAR(255)" . ")"; $this->_sql->query($cmd); $dir = Solar_Class::dir('Test_Solar_Auth_Adapter', '_support'); $insert = parse_ini_file($dir . 'users.ini', true); foreach ($insert as $handle => $data) { $data['handle'] = $handle; $data['passwd'] = hash('md5', $data['passwd']); $this->_sql->insert('members', $data); } $this->_moniker = 'Paul M. Jones'; $this->_email = '*****@*****.**'; $this->_uri = 'http://paul-m-jones.com'; $this->_config['sql'] = $this->_sql; $this->_config['table'] = 'members'; $this->_config['email_col'] = 'email'; $this->_config['moniker_col'] = 'moniker'; $this->_config['uri_col'] = 'uri'; parent::setup(); }
/** * * Run a single test method from the test class. * * @param Solar_Php $php The PHP execution object. * * @param string $class The test class. * * @param string $method The test method. * * @return void * */ protected function _testMethod($php, $class, $method) { $this->_test_result = null; $file = Solar_Class::dir($this) . 'run-test.php'; $php->setArgv(array($class, $method))->runSolar($file); $this->_done($php->getExitCode(), "{$class}::{$method}", $php->getLastLine()); }
/** * * Convenience method for getting a dump the whole object, or one of its * properties, or an external variable. * * @param mixed $var If null, dump $this; if a string, dump $this->$var; * otherwise, dump $var. * * @param string $label Label the dump output with this string. * * @return void * */ public function dump($var = null, $label = null) { $obj = Solar::factory('Solar_Debug_Var'); if (is_null($var)) { // clone $this and remove the parent config arrays $clone = clone $this; foreach (Solar_Class::parents($this) as $class) { $key = "_{$class}"; unset($clone->{$key}); } $obj->display($clone, $label); } elseif (is_string($var)) { // display a property $obj->display($this->{$var}, $label); } else { // display the passed variable $obj->display($var, $label); } }
/** * * Gets the option settings from the class hierarchy. * * @return array * */ protected function _fetchGetoptOptions() { // the options to be set $options = array(); // find the parents of this class, including this class $parents = Solar_Class::parents($this, true); array_shift($parents); // Solar_Base // get Info/options.php for each class in the stack foreach ($parents as $class) { $file = Solar_Class::file($class, 'Info/options.php'); if ($file) { $options = array_merge($options, (array) Solar_File::load($file)); } } return $options; }
/** * * Loads table name into $this->_table_name, and pre-sets the value of * $this->_inherit_name based on the class name. * * @return void * */ protected function _fixTableName() { /** * Pre-set the value of $_inherit_name. Will be modified one * more time in _fixPropertyCols(). */ // find the closest base called *_Model. we do this so that // we can honor the top-level table name with inherited models. // *do not* use the class stack, as Solar_Sql_Model has been // removed from it. $base_class = null; $base_name = null; $parents = array_reverse(Solar_Class::parents($this->_class, true)); foreach ($parents as $key => $val) { if (substr($val, -6) == '_Model') { // $key is now the value of the closest "_Model" class. -1 to // get the first class below that (e.g., *_Model_Nodes). // $base_class is then the class name that represents the // base of the model-inheritance hierarchy (which may not be // the immediate base in some cases). $base_class = $parents[$key - 1]; // the base model name (e.g., Nodes). $pos = strrpos($base_class, '_Model_'); if ($pos !== false) { // the part after "*_Model_" $base_name = substr($base_class, $pos + 7); } else { // the whole class name $base_name = $base_class; } break; } } // find the current model name (the part after "*_Model_") $pos = strrpos($this->_class, '_Model_'); if ($pos !== false) { $curr_name = substr($this->_class, $pos + 7); } else { $curr_name = $this->_class; } // compare base model name to the current model name. // if they are different, consider this class an inherited one. if ($curr_name != $base_name) { // Solar_Model_Bookmarks and Solar_Model_Nodes_Bookmarks // both result in "bookmarks". $len = strlen($base_name); if (substr($curr_name, 0, $len + 1) == "{$base_name}_") { $this->_inherit_name = substr($curr_name, $len + 1); } else { $this->_inherit_name = $curr_name; } // set the base-class for inheritance $this->_inherit_base = $base_class; } /** * Auto-set the table name, if needed; leave it alone if already * user-specified. */ if (empty($this->_table_name)) { // auto-define the table name. // change TableName to table_name. $this->_table_name = strtolower($this->_inflect->camelToUnder($base_name)); } }
/** * * Gets the option settings from the class hierarchy. * * @return array * */ protected function _getOptionSettings() { // the options to be set $options = array(); // find the parents of this class, including this class $parents = Solar_Class::parents(get_class($this), true); array_shift($parents); array_shift($parents); // get options.php for each parent class, as well as this class foreach ($parents as $class) { $file = str_replace('_', DIRECTORY_SEPARATOR, $class) . DIRECTORY_SEPARATOR . 'Info' . DIRECTORY_SEPARATOR . 'options.php'; $file = Solar_File::exists($file); if ($file) { $options = array_merge($options, (array) (include $file)); } } return $options; }
/** * * Sets the model stack. * * @param array $classes An array of class prefixes to use for the model * stack. * * @return void * */ protected function _setStack($classes) { if (!$classes) { // add per the vendor on this catalog and its inheritance $parents = Solar_Class::parents(get_class($this), true); array_shift($parents); // Solar_Base $old_vendor = false; foreach ($parents as $class) { $new_vendor = Solar_Class::vendor($class); if ($new_vendor != $old_vendor) { $classes[] = "{$new_vendor}_Model"; } $old_vendor = $new_vendor; } } // build the class stack $this->_stack = Solar::factory('Solar_Class_Stack'); $this->_stack->add($classes); }
/** * * Writes the "class" directory. * * @return void * */ public function writeClasses() { $this->_outln("Writing class pages to '{$this->_class_dir}':"); foreach ($this->api as $class => $api) { // ignore classes descended from Solar_Exception $parents = Solar_Class::parents($class); if (in_array('Solar_Exception', $parents)) { continue; } // write the class overview $this->_out("{$class}: "); $this->writeClassOverview($class); $this->_out('.'); // write the list of all config options and default values $this->writeClassConfig($class); $this->_out('.'); // write the list of all constants $this->writeClassConstants($class); $this->_out('.'); // write the list of all class properties $this->writeClassProperties($class); $this->_out("."); // write the list of all class methods $this->writeClassMethods($class); $this->_out('.'); // write each class method foreach ($api['methods'] as $name => $info) { $this->writeClassMethod($class, $name, $info); $this->_out('.'); } // write the class index $this->writeClassIndex($class); $this->_outln(". ;"); // retain the class name and info if ($api['summ']) { $this->_classes_list[$class] = $api['summ']; } else { $this->_classes_list[$class] = '-?-'; } } $this->_outln("Done."); // write the overall list of classes and summaries. $this->_out("Writing summary list of all classes ... "); $this->writeClassesIndex(); $this->_outln("done."); }
/** * * Given a class or object, add its vendor and its parent vendors to the * stack; optionally, add a standard suffix base to the vendor name. * * @param string|object $spec The class or object to find vendors of. * * @param string $base The suffix base to append to each vendor name. * * @return void * */ public function addByVendors($spec, $base = null) { // get the list of parents; retain Solar_Base $parents = Solar_Class::parents($spec, true); // if we have a suffix, put a separator on it if ($base) { $base = "_{$base}"; } // look through vendor names $old = null; foreach ($parents as $class) { $new = Solar_Class::vendor($class); if ($new != $old) { // not the same, add the current vendor name and suffix $this->add("{$new}{$base}"); } // retain old vendor for next loop $old = $new; } }
/** * * Returns the translated locale string for a class and key. * * Loads translations as needed. * * You can also pass an array of replacement values. If the `$replace` * array is sequential, this method will use it with vsprintf(); if the * array is associative, this method will replace "{:key}" with the array * value. * * For example: * * {{code: php * * $locale = Solar_Registry('locale'); * * $page = 2; * $pages = 10; * * // given a class of 'Solar_Example' with a locale string * // TEXT_PAGES => 'Page %d of %d', uses vsprintf() internally: * $replace = array($page, $pages); * echo $locale->fetch('Solar_Example', 'TEXT_PAGES', $pages, $replace); * // echo "Page 2 of 10" * * // given a class of 'Solar_Example' with a locale string * // TEXT_PAGES => 'Page {:page} of {:pages}', uses str_replace() * // internally: * $replace = array('page' => $page, 'pages' => $pages); * echo $locale->fetch('Solar_Example', 'TEXT_PAGES', $pages, $replace); * // echo "Page 2 of 10" * }} * * @param string|object $spec The class name (or object) for the translation. * * @param string $key The translation key. * * @param mixed $num Helps determine whether to get a singular * or plural translation. * * @param array $replace An array of replacement values for the string. * * @return string A translated locale string. * * @see _trans() * * @see Solar_Base::locale() * * @see Manual::Solar/Using_locales * */ public function fetch($spec, $key, $num = 1, $replace = null) { // is the spec an object? if (is_object($spec)) { // yes, find its class $class = get_class($spec); } else { // no, assume the spec is a class name $class = (string) $spec; } // does the translation key exist for this class? // pre-empts the stack check. $string = $this->_trans($class, $key, $num, $replace); if ($string !== null) { return $string; } // find all parents of the class, including the class itself $parents = array_reverse(Solar_Class::parents($class, true)); // add the vendor namespace to the stack for vendor-wide strings $vendor = Solar_Class::vendor($class); $parents[] = $vendor; // add Solar as the final fallback. if ($vendor != 'Solar') { $parents[] = 'Solar'; } // go through all parents and find the first matching key foreach ($parents as $parent) { // do we need to load locale strings for the class? if (!array_key_exists($parent, $this->trans)) { $this->_load($parent); } // does the key exist for the parent? $string = $this->_trans($parent, $key, $num, $replace); if ($string !== null) { // save it for the class so we don't need to go through the // stack again, and then we're done. $this->trans[$class][$key] = $this->trans[$parent][$key]; return $string; } } // never found a translation, return the requested key. return $key; }
protected function _postConstruct() { parent::_postConstruct(); $this->_support_path = Solar_Class::dir('Mock_Solar_Path_Stack'); }
public function testParents_includeSelf() { $actual = Solar_Class::parents('Mock_Solar_Exception_CustomCondition', true); $expect = array('Exception', 'Solar_Exception', 'Mock_Solar_Exception', 'Mock_Solar_Exception_CustomCondition'); $this->assertSame($actual, $expect); }
/** * * Creates the baseline PHP files in the Vendor directories from the * skeleton files in `Data/*.txt`. * * @return void * */ protected function _createFiles() { $system = Solar::$system; $data_dir = Solar_Class::dir($this, 'Data'); $list = glob($data_dir . "*.txt"); foreach ($list as $data_file) { $file = substr($data_file, strlen($data_dir)); $file = str_replace('.txt', '.php', $file); $file = str_replace('_', '/', $file); $file = str_replace('-', '_', $file); $file = "{$system}/source/{$this->_dashes}/{$this->_studly}/{$file}"; if (file_exists($file)) { $this->_outln("File {$file} exists."); continue; } $dirname = dirname($file); if (!is_dir($dirname)) { $this->_out("Making directory {$dirname} ... "); mkdir($dirname, 0755, true); $this->_outln("done."); } $text = file_get_contents($data_file); $text = str_replace('{:php}', '<?php', $text); $text = str_replace('{:vendor}', $this->_studly, $text); $this->_out("Writing {$file} ... "); file_put_contents($file, $text); $this->_outln("done."); } // write a "config/default.php" file $file = "{$system}/source/{$this->_dashes}/config/default.php"; if (file_exists($file)) { $this->_outln("File {$file} exists."); } else { $text = "<?php\n\$config = array();\nreturn \$config;\n"; $this->_out("Writing {$file} ... "); file_put_contents($file, $text); $this->_outln("done."); } // write a "config/run-tests.php" file $file = "{$system}/source/{$this->_dashes}/config/run-tests.php"; if (file_exists($file)) { $this->_outln("File {$file} exists."); } else { $text = "<?php\n\$config = array();\nreturn \$config;\n"; $this->_out("Writing {$file} ... "); file_put_contents($file, $text); $this->_outln("done."); } }
/** * * Generates a simple exception, but does not throw it. * * This method attempts to automatically load an exception class * based on the error code, falling back to parent exceptions * when no specific exception classes exist. For example, if a * class named 'Vendor_Example' extended from 'Vendor_Base' throws an * exception or error coded as 'ERR_FILE_NOT_FOUND', the method will * attempt to return these exception classes in this order ... * * 1. Vendor_Example_Exception_FileNotFound (class specific) * * 2. Vendor_Base_Exception_FileNotFound (parent specific) * * 3. Vendor_Example_Exception (class generic) * * 4. Vendor_Base_Exception (parent generic) * * 5. Vendor_Exception (generic for all of vendor) * * The final fallback is always the generic Solar_Exception class. * * Note that this method only generates the object; it does not * throw the exception. * * {{code: php * $class = 'My_Example_Class'; * $code = 'ERR_SOMETHING_WRONG'; * $text = 'Something is wrong.'; * $info = array('foo' => 'bar'); * $exception = Solar::exception($class, $code, $text, $info); * throw $exception; * }} * * In general, you shouldn't need to use this directly in classes * extended from [[Class::Solar_Base]]. Instead, use * [[Solar_Base::_exception() | $this->_exception()]] for automated * picking of the right exception class from the $code, and * automated translation of the error message. * * @param string|object $spec The class name (or object) that generated * the exception. * * @param mixed $code A scalar error code, generally a string. * * @param string $text Any error message text. * * @param array $info Additional error information in an associative * array. * * @return Solar_Exception * */ public static function exception($spec, $code, $text = '', $info = array()) { // is the spec an object? if (is_object($spec)) { // yes, find its class $class = get_class($spec); } else { // no, assume the spec is a class name $class = (string) $spec; } // drop 'ERR_' and 'EXCEPTION_' prefixes from the code // to get a suffix for the exception class $suffix = $code; if (strpos($suffix, 'ERR_') === 0) { $suffix = substr($suffix, 4); } elseif (strpos($suffix, 'EXCEPTION_') === 0) { $suffix = substr($suffix, 10); } // convert "STUDLY_CAP_SUFFIX" to "Studly Cap Suffix" ... $suffix = ucwords(strtolower(str_replace('_', ' ', $suffix))); // ... then convert to "StudlyCapSuffix" $suffix = str_replace(' ', '', $suffix); // build config array from params $config = array('class' => $class, 'code' => $code, 'text' => $text, 'info' => (array) $info); // get all parent classes, including the class itself $stack = array_reverse(Solar_Class::parents($class, true)); // add the vendor namespace to the stack as a fallback, even though // it's not strictly part of the hierarchy, for generic vendor-wide // exceptions. $vendor = Solar_Class::vendor($class); if ($vendor != 'Solar') { $stack[] = $vendor; } // add Solar as the final fallback $stack[] = 'Solar'; // track through class stack and look for specific exceptions foreach ($stack as $class) { try { $obj = Solar::factory("{$class}_Exception_{$suffix}", $config); return $obj; } catch (Exception $e) { // do nothing } } // track through class stack and look for generic exceptions foreach ($stack as $class) { try { $obj = Solar::factory("{$class}_Exception", $config); return $obj; } catch (Exception $e) { // do nothing } } // last resort: a generic Solar exception return Solar::factory('Solar_Exception', $config); }
/** * * Loads DocBook template files from the Data directory. * * @return void * */ protected function _loadTemplates() { $dir = Solar_Class::dir($this, 'Data'); $list = glob("{$dir}/*.xml"); foreach ($list as $file) { $name = basename($file); $this->_templates[$name] = file_get_contents($file); } }
/** * * Sets the class this app will extend from. * * @param string $class The app class name. * * @return void * */ protected function _setExtends($class) { // explicit as cli option? $extends = $this->_options['extends']; if ($extends) { $this->_extends = $extends; return; } // explicit as config value? if ($this->_model_name) { $extends = $this->_config['extends_model']; } else { $extends = $this->_config['extends']; } if ($extends) { $this->_extends = $extends; return; } // look at the vendor name and find a controller class $vendor = Solar_Class::vendor($class); if ($this->_model_name) { $name = "{$vendor}_Controller_Bread"; $file = $this->_target . "{$vendor}/Controller/Bread.php"; } else { $name = "{$vendor}_Controller_Page"; $file = $this->_target . "{$vendor}/Controller/Page.php"; } if (file_exists($file)) { $this->_extends = $name; return; } // final fallback: Solar_Controller_Page $this->_extends = 'Solar_Controller_Page'; return; }
/** * _setLayoutTemplates * Override Solar_Controller_Page _setLayoutTemplates * to add theme layout path to layout stack * */ protected function _setLayoutTemplates() { // get the parents of the current class, including self $stack = array_reverse(Solar_Class::parents($this, true)); // remove Solar_Base array_pop($stack); // convert underscores to slashes, and add /Layout foreach ($stack as $key => $val) { $stack[$key] = str_replace('_', '/', $val) . '/Layout'; } // add theme layout path if ($this->_controller == 'admin') { $theme_name = $this->blog_admin_theme; $theme_layout_path = Solar::$system . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . 'admin' . DIRECTORY_SEPARATOR . $theme_name . DIRECTORY_SEPARATOR . 'layouts'; $default_layout_path = Solar::$system . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . 'admin' . DIRECTORY_SEPARATOR . 'default' . DIRECTORY_SEPARATOR . 'layouts'; } else { $theme_name = $this->blog_theme; $theme_layout_path = Solar::$system . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . 'main' . DIRECTORY_SEPARATOR . $theme_name . DIRECTORY_SEPARATOR . 'layouts'; $default_layout_path = Solar::$system . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . 'main' . DIRECTORY_SEPARATOR . 'default' . DIRECTORY_SEPARATOR . 'layouts'; } if (Solar_Dir::exists($default_layout_path)) { array_unshift($stack, $default_layout_path); } if (Solar_Dir::exists($theme_layout_path) && $theme_layout_path != $default_layout_path) { array_unshift($stack, $theme_layout_path); } // done, add the stack $this->_view_object->setTemplatePath($stack); }
public function testDecode_compatFailure() { $pjson = $this->_newJson(); $njson = $this->_newExtJson(); $dir = Solar_Class::dir('Mock_Solar_Json'); $tests = scandir($dir); natsort($tests); foreach ($tests as $file) { if ($file == 'fail18.json') { // skip this one, because the userland implementation can't // handle it, but ext/json can. continue; } if (substr($file, 0, 4) == 'fail' && substr($file, -4) == 'json') { $before = file_get_contents($dir . $file); $this->diag("p: {$file}"); $this->assertNull($pjson->decode($before)); $this->diag("n: {$file}"); $this->assertNull($njson->decode($before)); } } }
/** * * Sets the class this model will extend from. * * @param string $class The model class name. * * @return void * */ protected function _setExtends($class) { // explicit as cli option? $extends = $this->_options['extends']; if ($extends) { $this->_extends = $extends; return; } // explicit as config value? $extends = $this->_config['extends']; if ($extends) { $this->_extends = $this->_config['extends']; return; } // look at the class name and find a Vendor_Sql_Model class $vendor = Solar_Class::vendor($class); $file = $this->_target . "{$vendor}/Sql/Model.php"; if (file_exists($file)) { $this->_extends = "{$vendor}_Sql_Model"; return; } // final fallback: Solar_Sql_Model $this->_extends = 'Solar_Sql_Model'; return; }