/** * Adds the structured data to the page body to be snippeted * * @param Doku_Event $event event object by reference * @param mixed $param [the parameters passed as fifth argument to register_hook() when this * handler was registered] * @return bool */ public function handle_snippets(Doku_Event $event, $param) { $id = $event->data['id']; $assignments = new Assignments(); $tables = $assignments->getPageAssignments($id); if (!$tables) { return; } foreach ($tables as $table) { $schemadata = AccessTable::byTableName($table, $id, 0); $event->data['text'] .= $schemadata->getDataPseudoSyntax(); } }
/** * Get the structured data of a given page * * @param string $page The page to get data for * @param string|null $schema The schema to use null for all * @param int $time A timestamp if you want historic data (0 for now) * @return array ('schema' => ( 'fieldlabel' => 'value', ...)) * @throws StructException */ public function getData($page, $schema = null, $time = 0) { $page = cleanID($page); if (is_null($schema)) { $assignments = new Assignments(); $schemas = $assignments->getPageAssignments($page, false); } else { $schemas = array($schema); } $result = array(); foreach ($schemas as $schema) { $schemaData = AccessTable::byTableName($schema, $page, $time); $result[$schema] = $schemaData->getDataArray(); } return $result; }
/** * Save the data, by loading it from the old revision and storing it as a new revision * * @param Doku_Event $event event object by reference * @param mixed $param [the parameters passed as fifth argument to register_hook() when this * handler was registered] * @return bool */ public function handle_pagesave_after(Doku_Event $event, $param) { global $ACT; global $REV; if ($ACT != 'revert' || !$REV) { return false; } $assignments = new Assignments(); // we load the data to restore from DB: $tosave = $assignments->getPageAssignments($event->data['id']); foreach ($tosave as $table) { $accessOld = AccessTable::byTableName($table, $event->data['id'], $REV); $accessNew = AccessTable::byTableName($table, $event->data['id'], $event->data['newRevision']); $accessNew->saveData($accessOld->getDataArray()); // make sure this schema is assigned $assignments->assignPageSchema($event->data['id'], $table); } return true; }
public function test_move() { $data = array('first' => 'data 1', 'second' => array('data 2.1', 'data 2.2'), 'third' => 'data 3', 'fourth' => 'data 4'); $empty = array('first' => '', 'second' => array(), 'third' => '', 'fourth' => ''); // add initial data $schemaData = meta\AccessTable::byTableName('schema1', 'somepage', time()); $schemaData->saveData($data); $this->assertEquals($data, $schemaData->getDataArray()); // fake move event $evdata = array('src_id' => 'somepage', 'dst_id' => 'newpage'); $event = new \Doku_Event('PLUGIN_MOVE_PAGE_RENAME', $evdata); $evhandler = new \action_plugin_struct_move(); $this->assertTrue($evhandler->handle_move($event, null)); // old page should be gone $schemaData = meta\AccessTable::byTableName('schema1', 'somepage', 0); $this->assertEquals($empty, $schemaData->getDataArray()); // new page should have data $schemaData = meta\AccessTable::byTableName('schema1', 'newpage', 0); $this->assertEquals($data, $schemaData->getDataArray()); }
/** * Create the form to edit schemadata * * @param string $tablename * @return string The HTML for this schema's form */ protected function createForm($tablename) { global $ID; global $REV; global $INPUT; if (auth_quickaclcheck($ID) == AUTH_READ) { return ''; } if (checklock($ID)) { return ''; } $schema = AccessTable::byTableName($tablename, $ID, $REV); if (!$schema->getSchema()->isEditable()) { return ''; } $schemadata = $schema->getData(); $structdata = $INPUT->arr(self::$VAR); if (isset($structdata[$tablename])) { $postdata = $structdata[$tablename]; } else { $postdata = array(); } // we need a short, unique identifier to use in the cookie. this should be good enough $schemaid = 'SRCT' . substr(str_replace(array('+', '/'), '', base64_encode(sha1($tablename, true))), 0, 5); $html = '<fieldset data-schema="' . $schemaid . '">'; $html .= '<legend>' . hsc($tablename) . '</legend>'; foreach ($schemadata as $field) { $label = $field->getColumn()->getLabel(); if (isset($postdata[$label])) { // posted data trumps stored data $field->setValue($postdata[$label], true); } $html .= $this->makeField($field, self::$VAR . "[{$tablename}][{$label}]"); } $html .= '</fieldset>'; return $html; }
/** * Add structured data to the diff * * This is done by adding pseudo syntax to the page source when it is loaded in diff context * * @param Doku_Event $event event object by reference * @param mixed $param [the parameters passed as fifth argument to register_hook() when this * handler was registered] * @return bool */ public function handle_diffload(Doku_Event $event, $param) { global $ACT; global $INFO; if ($ACT != 'diff') { return; } $id = $event->data[2]; $rev = $event->data[3]; if ($INFO['id'] != $id) { return; } $assignments = new Assignments(); $tables = $assignments->getPageAssignments($id); if (!$tables) { return; } $event->result .= "\n---- struct data ----\n"; foreach ($tables as $table) { $schemadata = AccessTable::byTableName($table, $id, $rev); $event->result .= $schemadata->getDataPseudoSyntax(); } $event->result .= "----\n"; }
public function test_filtervars_struct() { global $ID; $ID = 'foo:bar:baz'; // prepare some struct data $sb = new meta\SchemaImporter('schema1', file_get_contents(__DIR__ . '/json/schema1.struct.json')); $sb->build(); $schemaData = meta\AccessTable::byTableName('schema1', $ID, time()); $schemaData->saveData(array('first' => 'test', 'second' => array('multi1', 'multi2'))); $searchConfig = new SearchConfig(array('schemas' => array(array('schema1', 'alias')))); $this->assertEquals('test', $searchConfig->applyFilterVars('$STRUCT.first$')); $this->assertEquals('test', $searchConfig->applyFilterVars('$STRUCT.alias.first$')); $this->assertEquals('test', $searchConfig->applyFilterVars('$STRUCT.schema1.first$')); $this->assertEquals('pretestpost', $searchConfig->applyFilterVars('pre$STRUCT.first$post')); $this->assertEquals('pretestpost', $searchConfig->applyFilterVars('pre$STRUCT.alias.first$post')); $this->assertEquals('pretestpost', $searchConfig->applyFilterVars('pre$STRUCT.schema1.first$post')); $this->assertEquals(array('multi1', 'multi2'), $searchConfig->applyFilterVars('$STRUCT.second$')); $this->assertEquals(array('multi1', 'multi2'), $searchConfig->applyFilterVars('$STRUCT.alias.second$')); $this->assertEquals(array('multi1', 'multi2'), $searchConfig->applyFilterVars('$STRUCT.schema1.second$')); $this->assertEquals(array('premulti1post', 'premulti2post'), $searchConfig->applyFilterVars('pre$STRUCT.second$post')); $this->assertEquals(array('premulti1post', 'premulti2post'), $searchConfig->applyFilterVars('pre$STRUCT.alias.second$post')); $this->assertEquals(array('premulti1post', 'premulti2post'), $searchConfig->applyFilterVars('pre$STRUCT.schema1.second$post')); $this->assertEquals('', $searchConfig->applyFilterVars('$STRUCT.notexisting$')); }
/** * Save the struct data * * @param Doku_Event $event event object by reference * @param mixed $param [the parameters passed as fifth argument to register_hook() when this * handler was registered] * @return bool */ public function handle_save(Doku_Event $event, $param) { // get all struct values and their associated schemas $tosave = array(); foreach ($event->data['fields'] as $field) { if (!is_a($field, 'helper_plugin_struct_field')) { continue; } /** @var helper_plugin_struct_field $field */ $tbl = $field->column->getTable(); $lbl = $field->column->getLabel(); if (!isset($tosave[$tbl])) { $tosave[$tbl] = array(); } $tosave[$tbl][$lbl] = $field->getParam('value'); } // save all the struct data of assigned schemas $id = $event->data['id']; $time = filemtime(wikiFN($id)); $assignments = new Assignments(); $assigned = $assignments->getPageAssignments($id); foreach ($tosave as $table => $data) { if (!in_array($table, $assigned)) { continue; } $access = AccessTable::byTableName($table, $id, $time); $validator = $access->getValidator($data); if ($validator->validate()) { $validator->saveData($time); } } return true; }
public function test_getDataArray_skipEmpty() { // arrange $testdata = array('testcolumn' => '', 'testMulitColumn' => array("value2.1_saved", "value2.2_saved")); $schemaData = meta\AccessTable::byTableName('testtable', 'testpage', time()); $schemaData->saveData($testdata); // act $schemaData->optionSkipEmpty(true); $actual_data = $schemaData->getDataArray(); $expected_data = array('testMulitColumn' => array('value2.1_saved', 'value2.2_saved')); // assert $this->assertEquals(1, count($actual_data), 'There should be only one value returned and the empty value skipped'); $this->assertEquals($expected_data, $actual_data); }
/** * Render schema data * * Currently completely renderer agnostic * * @todo we currently have no schema headlines * * @param string $mode Renderer mode * @param Doku_Renderer $R The renderer * @param array $data The data from the handler() function * @return bool If rendering was successful. */ public function render($mode, Doku_Renderer $R, $data) { global $ID; global $INFO; global $REV; if ($ID != $INFO['id']) { return true; } if (!$INFO['exists']) { return true; } if ($this->hasBeenRendered) { return true; } // do not render the output twice on the same page, e.g. when another page has been included $this->hasBeenRendered = true; $assignments = new Assignments(); $tables = $assignments->getPageAssignments($ID); if (!$tables) { return true; } if ($mode == 'xhtml') { $R->doc .= '<div id="plugin__struct_output">'; } foreach ($tables as $table) { $schemadata = AccessTable::byTableName($table, $ID, $REV); $schemadata->optionSkipEmpty(true); $data = $schemadata->getData(); if (!count($data)) { continue; } $R->table_open(); $R->tablethead_open(); $R->tablerow_open(); $R->tableheader_open(2); $R->cdata($table); $R->tableheader_close(); $R->tablerow_close(); $R->tablethead_open(); $R->tabletbody_open(); foreach ($data as $field) { $R->tablerow_open(); $R->tableheader_open(); $R->cdata($field->getColumn()->getTranslatedLabel()); $R->tableheader_close(); $R->tablecell_open(); $field->render($R, $mode); $R->tablecell_close(); $R->tablerow_close(); } $R->tabletbody_close(); $R->table_close(); } if ($mode == 'xhtml') { $R->doc .= '</div>'; } return true; }
/** * Saves struct data for given page and schema * * Please note that setting the $rev only influences the struct data timestamp, * not the page and changelog entries. * * @param string $page * @param string $schema * @param array $data * @param int $rev allows to override the revision timestamp */ protected function saveData($page, $schema, $data, $rev = 0) { if (!$rev) { $rev = time(); } saveWikiText($page, "test for {$page}", "saved for testing"); $schemaData = AccessTable::byTableName($schema, $page, $rev); $schemaData->saveData($data); $assignments = new Assignments(); $assignments->assignPageSchema($page, $schema); }
/** * @group slow */ public function test_revert_page() { $page = 'test_revert_page'; $assignment = new meta\Assignments(); $schema = 'Schema2'; $assignment->addPattern($page, $schema); $wikitext = 'teststring'; global $conf; $conf['useacl'] = 1; $conf['superuser'] = '******'; $_SERVER['REMOTE_USER'] = '******'; //now it's testing as admin global $default_server_vars; $default_server_vars['REMOTE_USER'] = '******'; //Hack until Issue #1099 is fixed $USERINFO['grps'] = array('admin', 'user'); // first save; $request = new \TestRequest(); $structData = array($schema => array('afirst' => 'foo', 'asecond' => 'bar, baz', 'athird' => 'foobar', 'afourth' => '42')); $request->setPost('struct_schema_data', $structData); $request->setPost('wikitext', $wikitext); $request->setPost('summary', 'content and struct data saved'); $request->post(array('id' => $page, 'do' => 'save', 'sectok' => getSecurityToken()), '/doku.php'); $this->waitForTick(true); // second save $request = new \TestRequest(); $structData = array($schema => array('afirst' => 'foo2', 'asecond' => 'bar2, baz2', 'athird' => 'foobar2', 'afourth' => '43')); $request->setPost('struct_schema_data', $structData); $request->setPost('wikitext', $wikitext . $wikitext); $request->setPost('summary', 'delete page'); $request->post(array('id' => $page, 'do' => 'save', 'sectok' => getSecurityToken()), '/doku.php'); $this->waitForTick(true); // revert to first save $actpagelog = new \PageChangelog($page); $actrevisions = $actpagelog->getRevisions(0, 200); $actrevinfo = $actpagelog->getRevisionInfo($actrevisions[0]); $request = new \TestRequest(); $request->setPost('summary', 'revert page'); $request->post(array('id' => $page, 'do' => 'revert', 'rev' => $actrevinfo['date'], 'sectok' => getSecurityToken()), '/doku.php'); // assert $pagelog = new \PageChangelog($page); $revisions = $pagelog->getRevisions(-1, 200); $revinfo = $pagelog->getRevisionInfo($revisions[0]); $schemaData = meta\AccessTable::byTableName($schema, $page, 0); $actual_struct_data = $schemaData->getDataArray(); $expected_struct_data = array('afirst' => 'foo', 'asecond' => array('bar', 'baz'), 'athird' => 'foobar', 'afourth' => '42'); $this->assertEquals(3, count($revisions), 'there should be 3 (three) revisions'); $this->assertContains('restored', $revinfo['sum']); $this->assertEquals(DOKU_CHANGE_TYPE_REVERT, $revinfo['type']); $this->assertEquals($expected_struct_data, $actual_struct_data); // todo: timestamps? }
/** * Save one new lookup row */ protected function lookup_save() { global $INPUT; $tablename = $INPUT->str('schema'); $data = $INPUT->arr('entry'); action_plugin_struct_inline::checkCSRF(); $access = AccessTable::byTableName($tablename, 0, 0); if (!$access->getSchema()->isEditable()) { throw new StructException('lookup save error: no permission for schema'); } $validator = $access->getValidator($data); if (!$validator->validate()) { throw new StructException("Validation failed:\n%s", join("\n", $validator->getErrors())); } if (!$validator->saveData()) { throw new StructException('No data saved'); } // create a new row based on the original aggregation config for the new pid $pid = $access->getPid(); $config = json_decode($INPUT->str('searchconf'), true); $config['filter'] = array(array('%rowid%', '=', $pid, 'AND')); $lookup = new LookupTable('', 'xhtml', new Doku_Renderer_xhtml(), new SearchConfig($config)); echo $lookup->getFirstRow(); }
/** * Initialize internal state based on input variables * * @return bool if initialization was successfull */ protected function initFromInput() { global $INPUT; $this->schemadata = null; $this->column = null; $pid = $INPUT->str('pid'); list($table, $field) = explode('.', $INPUT->str('field')); if (blank($pid)) { return false; } if (blank($table)) { return false; } if (blank($field)) { return false; } $this->pid = $pid; try { $this->schemadata = AccessTable::byTableName($table, $pid); } catch (StructException $ignore) { return false; } $this->column = $this->schemadata->getSchema()->findColumn($field); if (!$this->column || !$this->column->isVisibleInEditor()) { $this->schemadata = null; $this->column = null; return false; } return true; }