Pelzini

This is the code documentation for the Pelzini project

source of /processor/database_outputter.php

Contains the DatabaseOutputter class
  1. <?php
  2. /*
  3. Copyright 2008 Josh Heidenreich
  4.  
  5. This file is part of Pelzini.
  6.  
  7. Pelzini is free software: you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation, either version 3 of the License, or
  10. (at your option) any later version.
  11.  
  12. Pelzini is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with Pelzini. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20.  
  21.  
  22. /**
  23.  * Contains the {@link DatabaseOutputter} class
  24.  *
  25.  * @package Outputters
  26.  * @author Josh
  27.  * @since 0.2
  28.  **/
  29.  
  30. /**
  31.  * Outputs the tree to a database.
  32.  **/
  33. abstract class DatabaseOutputter extends Outputter {
  34. static private $since_versions;
  35. protected $extra_insert_data = array();
  36.  
  37. /**
  38.   * Connects to the database
  39.   **/
  40. abstract protected function connect();
  41.  
  42. /**
  43.   * Executes a database query
  44.   */
  45. abstract protected function query($query);
  46.  
  47. /**
  48.   * Safens some input
  49.   * @param string $input The input to safen
  50.   **/
  51. abstract protected function sql_safen($input);
  52.  
  53.  
  54. /**
  55.   * Fetches a row from the database (numerical)
  56.   **/
  57. abstract protected function fetch_row($res);
  58.  
  59. /**
  60.   * Fetches a row from the database (assoc)
  61.   **/
  62. abstract protected function fetch_assoc($res);
  63.  
  64. /**
  65.   * Returns the number of rows affected in the last query
  66.   **/
  67. abstract protected function affected_rows($res);
  68.  
  69. /**
  70.   * Returns the autogenerated id created in the last query
  71.   **/
  72. abstract protected function insert_id();
  73.  
  74.  
  75. /**
  76.   * Returns an array of the tables in this database
  77.   **/
  78. abstract protected function get_table_list();
  79.  
  80. /**
  81.   * Should return a multi-dimentional array of the column details
  82.   * Format:
  83.   * Array [
  84.   * [0] => Array [
  85.   * 'Field' => field name
  86.   * 'Type' => field type, (e.g. 'serial', 'smallnum' or 'identifier')
  87.   * 'NotNull' => nullable?, (true or false)
  88.   * 'Key' => indexed?, ('PRI' for primary key)
  89.   * ]
  90.   * [1] => ...
  91.   * [n] => ...
  92.   **/
  93. abstract protected function get_column_details($table_name);
  94.  
  95. /**
  96.   * Should return a multi-dimentional array of the index details
  97.   * Format:
  98.   * Array [
  99.   * [0] => Array [
  100.   * 'Fields' => array of field names
  101.   * ]
  102.   * [1] => ...
  103.   * [n] => ...
  104.   **/
  105. abstract protected function get_index_details($table_name);
  106.  
  107. /**
  108.   * Gets the query that alters a column to match the new SQL definition
  109.   **/
  110. abstract protected function get_alter_column_query($table, $column_name, $new_type, $null_allowed);
  111.  
  112. /**
  113.   * Converts an internal type into the database-specific SQL type.
  114.   * The defined internal types are:
  115.   * - serial: a number that automatically increments whenever a record is added
  116.   * - smallnum: a small number. needs to be able to hold at least 32,767 possible values (e.g. a 16-bit signed integer)
  117.   * - largenum: a large number. needs to be the same size or larger than a serial type
  118.   * - string: a character field long enough to hold identifiers of objects (e.g. function names)
  119.   * - text: a field that can hold arbitary pieces of text larger than 65536 chars in length.
  120.   *
  121.   * @param string $internal_type_name The internal type name.
  122.   * @return string The name used by the SQL database.
  123.   **/
  124. abstract protected function get_sql_type($internal_type_name);
  125.  
  126. /**
  127.   * Creates a table
  128.   **/
  129. abstract protected function create_table($table_name, $columns);
  130.  
  131. /**
  132.   * The database engine should start a transaction. If transactions are not supported, it should do nothing.
  133.   **/
  134. abstract protected function start_transaction();
  135.  
  136. /**
  137.   * The database engine should commit a transaction. If transactions are not supported, it should do nothing.
  138.   **/
  139. abstract protected function commit_transaction();
  140.  
  141. /**
  142.   * The database engine should rollback a transaction. If transactions are not supported, it should do nothing.
  143.   **/
  144. abstract protected function rollback_transaction();
  145.  
  146.  
  147. /**
  148.   * Executes an insert query for the data provided.
  149.   **/
  150. protected function do_insert($table, $data)
  151. {
  152. $data += $this->extra_insert_data;
  153. $q = "INSERT INTO {$table} (";
  154. $q .= implode(', ', array_keys($data));
  155. $q .= ") VALUES (";
  156. $q .= implode(',', $data);
  157. $q .= ")";
  158. $this->query($q);
  159. }
  160.  
  161.  
  162. /**
  163.   * Executes an insert query for the data provided.
  164.   **/
  165. protected function do_multiple_insert($table, $data)
  166. {
  167. if (count($data) == 0) return;
  168.  
  169. $q = "INSERT INTO {$table} (";
  170. $q .= implode(',', array_keys($data[0] + $this->extra_insert_data));
  171. $q .= ") VALUES ";
  172.  
  173. $j = 0;
  174. foreach ($data as $row) {
  175. if ($j++ > 0) $q .= ',';
  176. $q .= '(' . implode(',', $row + $this->extra_insert_data) . ')';
  177. }
  178.  
  179. $this->query($q);
  180. }
  181.  
  182.  
  183. /**
  184.   * Executes an update query for the data provided.
  185.   **/
  186. protected function do_update($table, $data, $where)
  187. {
  188. $q = "UPDATE {$table} SET ";
  189. $j = 0;
  190. foreach ($data as $key => $val) {
  191. if ($j++) $q .= ',';
  192. $q .= $key . ' = ' . $val;
  193. }
  194. $q .= ' WHERE ';
  195. $j = 0;
  196. foreach ($where as $key => $val) {
  197. if ($j++) $q .= ',';
  198. $q .= $key . ' = ' . $val;
  199. }
  200. $this->query($q);
  201. }
  202.  
  203.  
  204. /**
  205.   * Updates the database layout to match the layout file
  206.   * NOTE: currently only supports column and table adding and updating, not removal.
  207.   *
  208.   * @param string $layout_filename The name of hte layout file to match
  209.   **/
  210. public function check_layout($layout_filename)
  211. {
  212. $layout_lines = file($layout_filename);
  213.  
  214. $res = $this->connect();
  215. if (! $res) {
  216. echo "<p>Unable to connect to database!";
  217. return false;
  218. }
  219.  
  220. $dest_tables = array ();
  221. $table = null;
  222.  
  223. foreach ($layout_lines as $line) {
  224. $line = trim($line);
  225. if ($line == '') continue;
  226.  
  227. $words = explode(' ', $line, 3);
  228.  
  229. switch ($words[0]) {
  230. case 'TABLE':
  231. $table = $words[1];
  232. break;
  233.  
  234. case 'PK':
  235. $dest_tables[$table]['PK'] = $words[1];
  236. break;
  237.  
  238. case 'INDEX':
  239. $dest_tables[$table]['Indexes'][] = $words[1];
  240. break;
  241.  
  242. default:
  243. $col = array();
  244. $col['Type'] = $words[1];
  245.  
  246. $col['NotNull'] = 0;
  247. if (isset($words[2])) {
  248. if ($words[2] == 'notnull') $col['NotNull'] = 1;
  249. if ($words[2] == 'null') $col['NotNull'] = 0;
  250. }
  251.  
  252. $dest_tables[$table]['Columns'][$words[0]] = $col;
  253. break;
  254. }
  255. }
  256.  
  257.  
  258. $curr_tables = array ();
  259.  
  260. $table_names = $this->get_table_list();
  261. foreach ($table_names as $table_name) {
  262. $curr_tables[$table_name] = array();
  263.  
  264. $colres = $this->get_column_details($table_name);
  265. foreach ($colres as $colrow) {
  266. $colrow['Type'] = strtolower($colrow['Type']);
  267.  
  268. if ($colrow['Key'] == 'PRI') {
  269. $curr_tables[$table_name]['PK'] = $colrow['Field'];
  270. }
  271. unset ($colrow['Key']);
  272.  
  273. $curr_tables[$table_name]['Columns'][$colrow['Field']] = $colrow;
  274. }
  275.  
  276. $indexres = $this->get_index_details($table_name);
  277. foreach ($indexres as $indexrow) {
  278. $curr_tables[$table_name]['Indexes'][] = $indexrow['Fields'][0];
  279. }
  280. }
  281.  
  282.  
  283.  
  284. foreach ($dest_tables as $table_name => $dest_table) {
  285. $curr_table = @$curr_tables[$table_name];
  286.  
  287. if ($curr_table === null) {
  288. // Create the table if it does not yet exist.
  289. echo "Create table {$table_name}.\n";
  290.  
  291. $this->create_table($table_name, $dest_table);
  292.  
  293.  
  294. } else {
  295. echo "Altering table {$table_name}\n";
  296.  
  297. // Update PK
  298. if ($curr_table['PK'] != $dest_table['PK']) {
  299. echo " Change primary key from {$curr_table['PK']} to {$dest_table['PK']}\n";
  300. /* not yet supported */
  301. }
  302.  
  303. // Update columns
  304. foreach ($dest_table['Columns'] as $column_name => $dest_column) {
  305. $curr_column = $curr_table['Columns'][$column_name];
  306.  
  307. $dest_sql = $this->get_sql_type($dest_column['Type']);
  308. if ($dest_column['NotNull']) $dest_sql .= ' not null';
  309.  
  310. if ($curr_column == null) {
  311. echo " Create column {$column_name}. New def: '{$dest_sql}'\n";
  312.  
  313. $q = "ALTER TABLE {$table_name} ADD COLUMN {$column_name} {$dest_sql}";
  314. echo " <b>Query: {$q}</b>\n";
  315.  
  316. $res = $this->query ($q);
  317. if ($res) echo ' Affected rows: ', $this->affected_rows($res), "\n";
  318.  
  319.  
  320. } else {
  321. $curr_sql = $this->get_sql_type($curr_column['Type']);
  322. if ($curr_column['NotNull']) $curr_sql .= ' not null';
  323.  
  324. if ($curr_sql != $dest_sql) {
  325. echo " Update col {$column_name}. Old def: '{$curr_sql}' New def: '{$dest_sql}'\n";
  326.  
  327. $q = $this->get_alter_column_query ($table_name, $column_name, $curr_column['Type'], $curr_column['NotNull']);
  328. echo " <b>Query: {$q}</b>\n";
  329.  
  330. $res = $this->query ($q);
  331. if ($res) echo ' Affected rows: ', $this->affected_rows($res), "\n";
  332.  
  333. } else {
  334. echo " Column {$column_name} does not need to be changed\n";
  335. }
  336. }
  337. }
  338.  
  339. // Update indexes
  340. foreach ($dest_table['Indexes'] as $column_name) {
  341. if (!in_array($column_name, $curr_table['Indexes'])) {
  342. echo " Create index {$column_name}\n";
  343.  
  344. $q = "ALTER TABLE {$table_name} ADD INDEX ({$column_name})";
  345. echo " <b>Query: {$q}</b>\n";
  346.  
  347. $res = $this->query ($q);
  348. if ($res) echo ' Affected rows: ', $this->affected_rows($res), "\n";
  349. }
  350. }
  351. }
  352.  
  353. echo "\n";
  354. }
  355. }
  356.  
  357.  
  358. /**
  359.   * Adds a @since version to from a {@link CodeParserItem} to the internal list
  360.   * This list is used to fill a table with all of the versions of the program in existance
  361.   **/
  362. static function addSinceVersion(CodeParserItem $parser_item, $parent)
  363. {
  364. if ($parser_item->since == '') return;
  365.  
  366. if (! in_array($parser_item->since, self::$since_versions)) {
  367. self::$since_versions[] = $parser_item->since;
  368. }
  369. }
  370.  
  371.  
  372. /**
  373.   * Gets the database id of a record for a specific @since version
  374.   **/
  375. private function getSinceVersionId($since_version)
  376. {
  377. $res = array_search($since_version, self::$since_versions);
  378. if ($res === false) return null;
  379. return $res + 1;
  380. }
  381.  
  382.  
  383. /**
  384.   * Does the actual outputting of the file objects (and theihttps://www.nationalcrimecheck.com.au/r sub-objects) to the database
  385.   *
  386.   * @param array $files The file objects to save to the database
  387.   * @param Config $config The project config
  388.   *
  389.   * @table insert projects The main project record
  390.   * @table insert packages All of the packages used by this project
  391.   * @table insert versions All of the project versions documented
  392.   * @table insert files All of the files
  393.   * @table insert documents All of the documents
  394.   **/
  395. public function output($files, Config $config)
  396. {
  397. $res = $this->connect();
  398. if (! $res) {
  399. echo "<p>Unable to connect to database!";
  400. return false;
  401. }
  402.  
  403. // Get existing or create new project
  404. $code = $this->sql_safen($config->getProjectCode());
  405. $res = $this->query("SELECT id FROM projects WHERE code = {$code}");
  406. $row = $this->fetch_assoc($res);
  407. if ($row) {
  408. // Update project details
  409. $project_id = $row['id'];
  410. $update_data = array();
  411. $update_data['name'] = $this->sql_safen($config->getProjectName());
  412. $update_data['license'] = $this->sql_safen($config->getLicenseText());
  413. $update_data['dategenerated'] = $this->sql_safen(date('Y-m-d h:i a'));
  414. $this->do_update('projects', $update_data, array('id' => $project_id));
  415.  
  416. } else {
  417. // Insert new project
  418. $insert_data = array();
  419. $insert_data['name'] = $this->sql_safen($config->getProjectName());
  420. $insert_data['code'] = $this->sql_safen($config->getProjectCode());
  421. $insert_data['license'] = $this->sql_safen($config->getLicenseText());
  422. $insert_data['dategenerated'] = $this->sql_safen(date('Y-m-d h:i a'));
  423. $this->do_insert('projects', $insert_data);
  424. $project_id = $this->insert_id();
  425. }
  426.  
  427. // Include project id in all inserts
  428. $this->extra_insert_data = array(
  429. 'projectid' => $project_id,
  430. );
  431.  
  432. // Only delete data from this project
  433. $this->query("DELETE FROM namespaces WHERE projectid = {$project_id}");
  434. $this->query("DELETE FROM files WHERE projectid = {$project_id}");
  435. $this->query("DELETE FROM functions WHERE projectid = {$project_id}");
  436. $this->query("DELETE FROM arguments WHERE projectid = {$project_id}");
  437. $this->query("DELETE FROM throws WHERE projectid = {$project_id}");
  438. $this->query("DELETE FROM returns WHERE projectid = {$project_id}");
  439. $this->query("DELETE FROM classes WHERE projectid = {$project_id}");
  440. $this->query("DELETE FROM class_implements WHERE projectid = {$project_id}");
  441. $this->query("DELETE FROM interfaces WHERE projectid = {$project_id}");
  442. $this->query("DELETE FROM variables WHERE projectid = {$project_id}");
  443. $this->query("DELETE FROM constants WHERE projectid = {$project_id}");
  444. $this->query("DELETE FROM item_authors WHERE projectid = {$project_id}");
  445. $this->query("DELETE FROM item_tables WHERE projectid = {$project_id}");
  446. $this->query("DELETE FROM documents WHERE projectid = {$project_id}");
  447. $this->query("DELETE FROM versions WHERE projectid = {$project_id}");
  448. $this->query("DELETE FROM item_see WHERE projectid = {$project_id}");
  449. $this->query("DELETE FROM item_example WHERE projectid = {$project_id}");
  450. $this->query("DELETE FROM enumerations WHERE projectid = {$project_id}");
  451. $this->query("DELETE FROM item_info_tags WHERE projectid = {$project_id}");
  452.  
  453. $namespaces = array();
  454. foreach ($files as $file) {
  455. if (empty($file->namespace)) continue;
  456.  
  457. $parent_id = 0;
  458. $components = array();
  459. foreach ($file->namespace as $ns) {
  460. $components[] = $ns;
  461. $full_namespace = implode('\\', $components);
  462.  
  463. if (!isset($namespaces[$full_namespace])) {
  464. $insert_data = array();
  465. $insert_data['name'] = $this->sql_safen($full_namespace);
  466. $insert_data['parentid'] = $parent_id;
  467. $this->do_insert('namespaces', $insert_data);
  468. $namespaces[$full_namespace] = $this->insert_id();
  469. }
  470.  
  471. $parent_id = $namespaces[$full_namespace];
  472. }
  473. }
  474.  
  475. // Determine the versions that are available
  476. self::$since_versions = array();
  477. foreach ($files as $item) {
  478. if ($item instanceof ParserFile) {
  479. $item->treeWalk(array('DatabaseOutputter', 'addSinceVersion'));
  480. }
  481. }
  482.  
  483. // Sorts the versions array
  484. natsort(self::$since_versions);
  485. self::$since_versions = array_reverse(self::$since_versions);
  486.  
  487. // And add them to the table
  488. foreach (self::$since_versions as $version) {
  489. $insert_data = array();
  490. $insert_data['name'] = $this->sql_safen($version);
  491. $this->do_insert('versions', $insert_data);
  492. }
  493.  
  494. // go through all the files
  495. foreach ($files as $item) {
  496. if ($item instanceof ParserFile) {
  497. if ($item->namespace) {
  498. $file_namespace = $namespaces[implode('\\', $item->namespace)];
  499. } else {
  500. $file_namespace = 0;
  501. }
  502.  
  503. $insert_data = array();
  504. $insert_data['name'] = $this->sql_safen($item->name);
  505. $insert_data['description'] = $this->sql_safen($item->description);
  506. $insert_data['source'] = $this->sql_safen($item->source);
  507. $insert_data['sinceid'] = $this->sql_safen($this->getSinceVersionId($item->since));
  508. $insert_data['namespaceid'] = $this->sql_safen($file_namespace);
  509.  
  510. $this->do_insert('files', $insert_data);
  511. $file_id = $this->insert_id ();
  512.  
  513. // this files functions
  514. foreach ($item->functions as $function) {
  515. $this->save_function($function, $file_id, null, null, $file_namespace);
  516. }
  517.  
  518. // this files classes
  519. foreach ($item->classes as $class) {
  520. if ($class instanceof ParserClass) {
  521. $this->save_class($class, $file_id, $file_namespace);
  522. } else if ($class instanceof ParserInterface) {
  523. $this->save_interface($class, $file_id, $file_namespace);
  524. }
  525. }
  526.  
  527. // this files constants
  528. foreach ($item->constants as $constant) {
  529. $this->save_constant($constant, $file_id);
  530. }
  531.  
  532. // this files enums
  533. foreach ($item->enumerations as $enumeration) {
  534. $this->save_enumeration($enumeration, $file_id);
  535. }
  536.  
  537. // Common items
  538. $this->save_author_items (LINK_TYPE_FILE, $file_id, $item->authors);
  539. $this->save_table_items (LINK_TYPE_FILE, $file_id, $item->tables);
  540. $this->save_see_items (LINK_TYPE_FILE, $file_id, $item->see);
  541. $this->save_example_items (LINK_TYPE_FILE, $file_id, $item->example);
  542. $this->save_info_tag_items (LINK_TYPE_FILE, $file_id, $item->info_tags);
  543.  
  544.  
  545. } else if ($item instanceof ParserDocument) {
  546. // Inserts a document
  547. $insert_data = array();
  548. $insert_data['name'] = $this->sql_safen($item->name);
  549. $insert_data['description'] = $this->sql_safen($item->description);
  550.  
  551. $this->do_insert('documents', $insert_data);
  552.  
  553.  
  554. }
  555. }
  556.  
  557. //$this->commit_transaction();
  558.  
  559. return true;
  560. }
  561.  
  562.  
  563. /**
  564.   * Saves a function to the database
  565.   *
  566.   * @table insert functions Adds the function details
  567.   * @table insert arguments Adds the arguments for this function
  568.   **/
  569. private function save_function($function, $file_id, $class_id, $interface_id, $file_namespace)
  570. {
  571. // Ignore closures
  572. if ($function->name == null) return;
  573.  
  574. // prepare data for inserting
  575. $insert_data = array();
  576. $insert_data['static'] = 0;
  577. $insert_data['final'] = 0;
  578. $insert_data['abstract'] = 0;
  579. $insert_data['name'] = $this->sql_safen($function->name);
  580. $insert_data['description'] = $this->sql_safen($function->description);
  581. $insert_data['fileid'] = $file_id;
  582. $insert_data['deprecated'] = $this->sql_safen($function->deprecated);
  583. $insert_data['linenum'] = $this->sql_safen($function->linenum);
  584. $insert_data['sinceid'] = $this->sql_safen($this->getSinceVersionId($function->since));
  585. $insert_data['namespaceid'] = $this->sql_safen($file_namespace);
  586.  
  587. // Class-specific details
  588. if ($class_id != null) {
  589. $insert_data['classid'] = $class_id;
  590. $insert_data['visibility'] = $this->sql_safen($function->visibility);
  591.  
  592. // Interface-specific details
  593. } else if ($interface_id != null) {
  594. $insert_data['interfaceid'] = $interface_id;
  595. $insert_data['visibility'] = $this->sql_safen($function->visibility);
  596. }
  597.  
  598. if ($function->static) $insert_data['static'] = 1;
  599. if ($function->final) $insert_data['final'] = 1;
  600.  
  601. // build arguments string
  602. if (count($function->args) > 0) {
  603. $args = array();
  604. foreach ($function->args as $arg) {
  605. if ($arg->type != null) {
  606. $args[] = $arg->type . ' ' . $arg->name;
  607. } else {
  608. $args[] = $arg->name;
  609. }
  610. }
  611. $insert_data['arguments'] = $this->sql_safen(implode(', ', $args));
  612.  
  613. } else {
  614. $insert_data['arguments'] = "''";
  615. }
  616.  
  617. // build query from prepared data
  618. $this->do_insert('functions', $insert_data);
  619. $function_id = $this->insert_id ();
  620.  
  621.  
  622. // Insert common items
  623. $this->save_author_items (LINK_TYPE_FUNCTION, $function_id, $function->authors);
  624. $this->save_table_items (LINK_TYPE_FUNCTION, $function_id, $function->tables);
  625. $this->save_see_items (LINK_TYPE_FUNCTION, $function_id, $function->see);
  626. $this->save_example_items (LINK_TYPE_FUNCTION, $function_id, $function->example);
  627. $this->save_info_tag_items (LINK_TYPE_FUNCTION, $function_id, $function->info_tags);
  628.  
  629. // insert arguments
  630. $args = array();
  631. foreach ($function->args as $arg) {
  632. $insert_data = array();
  633. $insert_data['name'] = $this->sql_safen($arg->name);
  634. $insert_data['type'] = $this->sql_safen($arg->type);
  635. $insert_data['byref'] = ($arg->byref ? '1' : '0');
  636. $insert_data['defaultvalue'] = $this->sql_safen($arg->default);
  637. $insert_data['description'] = $this->sql_safen($arg->description);
  638. $insert_data['functionid'] = $this->sql_safen($function_id);
  639. $args[] = $insert_data;
  640. }
  641. $this->do_multiple_insert('arguments', $args);
  642.  
  643. // insert throws
  644. $throws = array();
  645. foreach ($function->throws as $arg) {
  646. $insert_data = array();
  647. $insert_data['exception'] = $this->sql_safen($arg->exception);
  648. $insert_data['description'] = $this->sql_safen($arg->description);
  649. $insert_data['functionid'] = $this->sql_safen($function_id);
  650. $throws[] = $insert_data;
  651. }
  652. $this->do_multiple_insert('throws', $throws);
  653.  
  654. // insert return values
  655. $returns = array();
  656. foreach ($function->returns as $ret) {
  657. $insert_data = array();
  658. $insert_data['type'] = $this->sql_safen($ret->type);
  659. $insert_data['description'] = $this->sql_safen($ret->description);
  660. $insert_data['functionid'] = $this->sql_safen($function_id);
  661. $returns[] = $insert_data;
  662. }
  663. $this->do_multiple_insert('returns', $returns);
  664. }
  665.  
  666.  
  667. /**
  668.   * Saves a class to the database
  669.   *
  670.   * @table insert classes Adds the class information for this class
  671.   * @table insert class_implements Adds the interfaces that this class extends
  672.   **/
  673. private function save_class($class, $file_id, $file_namespace)
  674. {
  675. // prepare the data for inserting
  676. $insert_data = array();
  677. $insert_data['abstract'] = 0;
  678. $insert_data['final'] = 0;
  679. $insert_data['name'] = $this->sql_safen($class->name);
  680. $insert_data['description'] = $this->sql_safen($class->description);
  681. $insert_data['extends'] = $this->sql_safen($class->extends);
  682. $insert_data['visibility'] = $this->sql_safen($class->visibility);
  683. $insert_data['fileid'] = $file_id;
  684. $insert_data['deprecated'] = $this->sql_safen($class->deprecated);
  685. $insert_data['linenum'] = $this->sql_safen($class->linenum);
  686. $insert_data['sinceid'] = $this->sql_safen($this->getSinceVersionId($class->since));
  687. $insert_data['namespaceid'] = $this->sql_safen($file_namespace);
  688.  
  689. if ($class->abstract) $insert_data['abstract'] = 1;
  690. if ($class->final) $insert_data['final'] = 1;
  691.  
  692. // Build and process query from prepared data
  693. $this->do_insert('classes', $insert_data);
  694. $class_id = $this->insert_id ();
  695.  
  696. // process implements
  697. foreach ($class->implements as $implements) {
  698. $insert_data = array();
  699. $insert_data['classid'] = $class_id;
  700. $insert_data['name'] = $this->sql_safen($implements);
  701.  
  702. $this->do_insert('class_implements', $insert_data);
  703. }
  704.  
  705.  
  706. // process functions
  707. foreach ($class->functions as $function) {
  708. $this->save_function($function, $file_id, $class_id, null, $file_namespace);
  709. }
  710.  
  711. // process variables
  712. foreach ($class->variables as $variable) {
  713. $this->save_variable($variable, $class_id);
  714. }
  715.  
  716. // Insert common items
  717. $this->save_author_items (LINK_TYPE_CLASS, $class_id, $class->authors);
  718. $this->save_table_items (LINK_TYPE_CLASS, $class_id, $class->tables);
  719. $this->save_see_items (LINK_TYPE_CLASS, $class_id, $class->see);
  720. $this->save_example_items (LINK_TYPE_CLASS, $class_id, $class->example);
  721. $this->save_info_tag_items (LINK_TYPE_CLASS, $class_id, $class->info_tags);
  722. }
  723.  
  724.  
  725. /**
  726.   * Saves an interface to the database
  727.   *
  728.   * @table insert interfaces
  729.   **/
  730. private function save_interface($interface, $file_id, $file_namespace)
  731. {
  732. // prepare the data for inserting
  733. $insert_data = array();
  734. $insert_data['name'] = $this->sql_safen($interface->name);
  735. $insert_data['description'] = $this->sql_safen($interface->description);
  736. $insert_data['extends'] = $this->sql_safen($interface->extends);
  737. $insert_data['visibility'] = $this->sql_safen($interface->visibility);
  738. $insert_data['fileid'] = $file_id;
  739. $insert_data['deprecated'] = $this->sql_safen($interface->deprecated);
  740. $insert_data['linenum'] = $this->sql_safen($interface->linenum);
  741. $insert_data['sinceid'] = $this->sql_safen($this->getSinceVersionId($interface->since));
  742. $insert_data['namespaceid'] = $this->sql_safen($file_namespace);
  743.  
  744. // Build and process query from prepared data
  745. $this->do_insert('interfaces', $insert_data);
  746. $interface_id = $this->insert_id ();
  747.  
  748.  
  749. // process functions
  750. foreach ($interface->functions as $function) {
  751. $this->save_function ($function, $file_id, null, $interface_id, $file_namespace);
  752. }
  753.  
  754. // insert common items
  755. $this->save_author_items (LINK_TYPE_INTERFACE, $interface_id, $interface->authors);
  756. $this->save_see_items (LINK_TYPE_INTERFACE, $interface_id, $interface->see);
  757. $this->save_example_items (LINK_TYPE_INTERFACE, $interface_id, $interface->example);
  758. $this->save_info_tag_items (LINK_TYPE_INTERFACE, $interface_id, $interface->info_tags);
  759. }
  760.  
  761.  
  762. /**
  763.   * Saves a variable to the database
  764.   *
  765.   * @table insert variables
  766.   **/
  767. private function save_variable($variable, $class_id = null, $interface_id = null)
  768. {
  769. // prepare data for inserting
  770. $insert_data = array();
  771. $insert_data['static'] = 0;
  772. $insert_data['name'] = $this->sql_safen($variable->name);
  773. $insert_data['description'] = $this->sql_safen($variable->description);
  774. //$insert_data['visibility'] = $this->sql_safen($variable->visibility);
  775. $insert_data['sinceid'] = $this->sql_safen($this->getSinceVersionId($variable->since));
  776.  
  777.  
  778. // Class-specific details
  779. if ($class_id != null) {
  780. $insert_data['classid'] = $class_id;
  781.  
  782. // Interface-specific details
  783. } else if ($interface_id != null) {
  784. $insert_data['interfaceid'] = $interface_id;
  785. }
  786.  
  787. if ($variable->static) $insert_data['static'] = 1;
  788.  
  789.  
  790. // Build and process query from prepared data
  791. $this->do_insert('variables', $insert_data);
  792. $variable_id = $this->insert_id ();
  793.  
  794. // insert common items
  795. $this->save_author_items (LINK_TYPE_VARIABLE, $variable_id, $variable->authors);
  796. $this->save_see_items (LINK_TYPE_VARIABLE, $variable_id, $variable->see);
  797. $this->save_example_items (LINK_TYPE_VARIABLE, $variable_id, $variable->example);
  798. $this->save_info_tag_items (LINK_TYPE_VARIABLE, $variable_id, $variable->info_tags);
  799. }
  800.  
  801.  
  802. /**
  803.   * Saves a constant to the database
  804.   *
  805.   * @table insert constants
  806.   **/
  807. private function save_constant($constant, $file_id = null, $enumeration_id = null)
  808. {
  809. // prepare data for inserting
  810. $insert_data = array();
  811. $insert_data['name'] = $this->sql_safen($constant->name);
  812. $insert_data['value'] = $this->sql_safen($constant->value);
  813. $insert_data['description'] = $this->sql_safen($constant->description);
  814. $insert_data['fileid'] = $this->sql_safen($file_id);
  815. $insert_data['linenum'] = $this->sql_safen($constant->linenum);
  816. $insert_data['sinceid'] = $this->sql_safen($this->getSinceVersionId($constant->since));
  817.  
  818. if ($enumeration_id != null) {
  819. $insert_data['enumerationid'] = $enumeration_id;
  820. }
  821.  
  822. // Build and process query from prepared data
  823. $this->do_insert('constants', $insert_data);
  824. $constant_id = $this->insert_id ();
  825.  
  826. // insert common items
  827. $this->save_author_items (LINK_TYPE_CONSTANT, $constant_id, $constant->authors);
  828. $this->save_see_items (LINK_TYPE_CONSTANT, $constant_id, $constant->see);
  829. $this->save_example_items (LINK_TYPE_CONSTANT, $constant_id, $constant->example);
  830. $this->save_info_tag_items (LINK_TYPE_CONSTANT, $constant_id, $constant->info_tags);
  831. }
  832.  
  833.  
  834. /**
  835.   * Saves a enumeration to the database
  836.   *
  837.   * @table insert enumerations
  838.   **/
  839. private function save_enumeration($enumeration, $file_id = null)
  840. {
  841. // prepare data for inserting
  842. $insert_data = array();
  843. $insert_data['name'] = $this->sql_safen($enumeration->name);
  844. $insert_data['description'] = $this->sql_safen($enumeration->description);
  845. $insert_data['fileid'] = $this->sql_safen($file_id);
  846. $insert_data['linenum'] = $this->sql_safen($enumeration->linenum);
  847. $insert_data['sinceid'] = $this->sql_safen($this->getSinceVersionId($constant->since));
  848. $insert_data['virtual'] = $this->sql_safen($enumeration->virtual);
  849.  
  850. // Build and process query from prepared data
  851. $this->do_insert('enumerations', $insert_data);
  852. $enumeration_id = $this->insert_id ();
  853.  
  854. // insert common items
  855. $this->save_author_items (LINK_TYPE_ENUMERATION, $enumeration_id, $enumeration->authors);
  856. $this->save_see_items (LINK_TYPE_ENUMERATION, $enumeration_id, $enumeration->see);
  857. $this->save_example_items (LINK_TYPE_ENUMERATION, $enumeration_id, $enumeration->example);
  858. $this->save_info_tag_items (LINK_TYPE_ENUMERATION, $enumeration_id, $enumeration->info_tags);
  859.  
  860. // Save the constants for this enumeration
  861. foreach ($enumeration->constants as $constant) {
  862. $this->save_constant ($constant, $file_id, $enumeration_id);
  863. }
  864. }
  865.  
  866.  
  867. /**
  868.   * Saves author information about an item
  869.   *
  870.   * @table insert item_authors
  871.   **/
  872. private function save_author_items($link_type, $link_id, $items)
  873. {
  874. $rows = array();
  875. foreach ($items as $item) {
  876. $insert_data = array();
  877. $insert_data['linkid'] = $this->sql_safen($link_id);
  878. $insert_data['linktype'] = $this->sql_safen($link_type);
  879. $insert_data['name'] = $this->sql_safen($item->name);
  880. $insert_data['email'] = $this->sql_safen($item->email);
  881. $insert_data['description'] = $this->sql_safen($item->description);
  882. $rows[] = $insert_data;
  883. }
  884. $this->do_multiple_insert('item_authors', $rows);
  885. }
  886.  
  887.  
  888. /**
  889.   * Saves table usage information about an item
  890.   *
  891.   * @since 0.2
  892.   * @table insert item_tables Adds information about the tables that are used by a function, class or file.
  893.   **/
  894. private function save_table_items($link_type, $link_id, $items)
  895. {
  896. $rows = array();
  897. foreach ($items as $item) {
  898. $insert_data = array();
  899. $insert_data['linkid'] = $this->sql_safen($link_id);
  900. $insert_data['linktype'] = $this->sql_safen($link_type);
  901. $insert_data['name'] = $this->sql_safen($item->name);
  902. $insert_data['action'] = $this->sql_safen($item->action);
  903. $insert_data['description'] = $this->sql_safen($item->description);
  904. $rows[] = $insert_data;
  905. }
  906. $this->do_multiple_insert('item_tables', $rows);
  907. }
  908.  
  909.  
  910. /**
  911.   * Saves 'see also' information about an item
  912.   *
  913.   * @since 0.2
  914.   * @table insert item_see Adds 'see also' links for a function, class, file, etc.
  915.   **/
  916. private function save_see_items($link_type, $link_id, $items)
  917. {
  918. $rows = array();
  919. foreach ($items as $item) {
  920. $insert_data = array();
  921. $insert_data['linkid'] = $this->sql_safen($link_id);
  922. $insert_data['linktype'] = $this->sql_safen($link_type);
  923. $insert_data['name'] = $this->sql_safen($item);
  924. $rows[] = $insert_data;
  925. }
  926. $this->do_multiple_insert('item_see', $rows);
  927. }
  928.  
  929.  
  930. /**
  931.   * Saves 'example' information about an item
  932.   *
  933.   * @table insert item_example Adds examples for a function, class, file, etc.
  934.   **/
  935. private function save_example_items($link_type, $link_id, $items)
  936. {
  937. $rows = array();
  938. foreach ($items as $item) {
  939. $insert_data = array();
  940. $insert_data['linkid'] = $this->sql_safen($link_id);
  941. $insert_data['linktype'] = $this->sql_safen($link_type);
  942. $insert_data['description'] = $this->sql_safen($item);
  943. $rows[] = $insert_data;
  944. }
  945. $this->do_multiple_insert('item_example', $rows);
  946. }
  947.  
  948.  
  949. /**
  950.   * Saves info tags for an item
  951.   *
  952.   * @since 0.3
  953.   * @table insert item_info_tags Adds info tags links for a function, class, file, etc.
  954.   **/
  955. private function save_info_tag_items($link_type, $link_id, $items)
  956. {
  957. $rows = array();
  958. foreach ($items as $item) {
  959. $insert_data = array();
  960. $insert_data['linkid'] = $this->sql_safen($link_id);
  961. $insert_data['linktype'] = $this->sql_safen($link_type);
  962. $insert_data['name'] = $this->sql_safen($item);
  963. $rows[] = $insert_data;
  964. }
  965. $this->do_multiple_insert('item_info_tags', $rows);
  966. }
  967.  
  968.  
  969. }
  970.  
  971.  
  972. ?>
  973.