diff --git a/bin/recreateIndexes.php b/bin/recreateIndexes.php new file mode 100644 index 0000000..437872e --- /dev/null +++ b/bin/recreateIndexes.php @@ -0,0 +1,781 @@ +globalStart(); + +do +{ + $dropped = $recreator->dropIndexes(); +} while ($dropped != 0); + +$recreator->applyPreFixes(); +$recreator->addPrimaryKeys(); +$recreator->addForeignKeys(); +$recreator->removeDuplicateIndexes(); +$recreator->addOtherIndexes(); +$recreator->applyPostFixes(); + +print sprintf(_kt('Total time: %s'), $recreator->globalEnd()); + +print _kt('Done.') . "\n"; +exit; + +class IndexRecreator +{ + var $knownKeys; + var $knownPrimary; + var $newPrimary; + var $newKeys; + var $exec; + var $debugSQL = false; + var $verbose = true; + + var $foreignkeys; + var $primary; + var $globalstart; + var $start; + + function microtimeFloat() + { + list($usec, $sec) = explode(" ", microtime()); + return ((float)$usec + (float)$sec); + } + + function globalStart() + { + $this->globalstart = $this->microtimeFloat(); + } + + function start() + { + $this->start = $this->microtimeFloat(); + } + + function globalEnd() + { + $time = $this->microtimeFloat() - $this->globalstart; + + return number_format($time,2,'.',',') . 's'; + } + + function end() + { + $time = $this->microtimeFloat() - $this->start; + return number_format($time,2,'.',',') . "s"; + } + + function IndexRecreator() + { + $this->knownKeys = array(); + $this->knownPrimary = array(); + $this->newPrimary = array(); + $this->newKeys = array(); + $this->exec = true; + } + + function applyPreFixes() + { + + } + + function addForeignKeys() + { + $this->addForeignKey('active_sessions', 'user_id', 'users', 'id'); + + $this->addForeignKey('archive_restoration_request', 'document_id', 'documents', 'id'); + $this->addForeignKey('archive_restoration_request', 'request_user_id', 'users', 'id'); + $this->addForeignKey('archive_restoration_request', 'admin_user_id', 'users', 'id'); + + $this->addForeignKey('archiving_settings', 'archiving_type_id', 'archiving_type_lookup', 'id'); + $this->addForeignKey('archiving_settings', 'time_period_id', 'time_period', 'id'); + + $this->addForeignKey('baobab_user_keys', 'user_id', 'users', 'id'); + $this->addForeignKey('baobab_user_keys', 'key_id', 'baobab_keys', 'id'); + + $this->addForeignKey('comment_searchable_text', 'comment_id', 'discussion_comments', 'id'); + $this->addForeignKey('comment_searchable_text', 'document_id', 'documents', 'id'); + + $this->addForeignKey('dashlet_disables', 'user_id', 'users', 'id'); + + $this->addForeignKey('discussion_comments', 'thread_id', 'discussion_threads', 'id'); + $this->addForeignKey('discussion_comments', 'user_id', 'users', 'id'); + $this->addForeignKey('discussion_comments', 'in_reply_to', 'discussion_comments', 'id'); + + $this->addForeignKey('discussion_threads', 'document_id', 'documents', 'id'); + + $this->addForeignKey('document_archiving_link', 'document_id', 'documents', 'id'); + $this->addForeignKey('document_archiving_link', 'archiving_settings_id', 'archiving_settings', 'id'); + + $this->addForeignKey('document_content_version', 'document_id', 'documents', 'id'); + $this->addForeignKey('document_content_version', 'mime_id', 'mime_types', 'id'); + + $this->addForeignKey('document_fields','parent_fieldset','fieldsets','id'); + + $this->addForeignKey('document_fields_link','document_field_id','document_fields','id'); + $this->addForeignKey('document_fields_link','metadata_version_id','document_metadata_version','id'); + + $this->addForeignKey('document_link','parent_document_id', 'documents', 'id'); + $this->addForeignKey('document_link','child_document_id', 'documents', 'id'); + $this->addForeignKey('document_link','link_type_id','document_link_types','id'); + + $this->addForeignKey('document_metadata_version','document_type_id','document_types_lookup','id'); + $this->addForeignKey('document_metadata_version','status_id','status_lookup','id'); + $this->addForeignKey('document_metadata_version','document_id','documents','id'); + $this->addForeignKey('document_metadata_version','version_creator_id','users','id'); + $this->addForeignKey('document_metadata_version','content_version_id','document_content_version','id'); + $this->addForeignKey('document_metadata_version','workflow_id','workflows','id'); + $this->addForeignKey('document_metadata_version','workflow_state_id','workflow_states','id'); + + $this->addForeignKey('document_role_allocations','role_id','roles','id'); + $this->addForeignKey('document_role_allocations','permission_descriptor_id','permission_descriptors','id'); + + $this->addForeignKey('document_searchable_text','document_id','documents','id'); + + $this->addForeignKey('document_subscriptions','user_id','users','id'); + $this->addForeignKey('document_subscriptions','document_id','documents','id'); + + $this->addForeignKey('document_tags','document_id','documents','id'); + $this->addForeignKey('document_tags','tag_id','tag_words','id'); + + $this->addForeignKey('document_text','document_id','documents','id'); + + + $this->addForeignKey('document_transaction_text','document_id','documents','id'); + + $this->addForeignKey('document_transactions','document_id','documents','id', 'SET NULL', 'SET NULL'); + $this->addForeignKey('document_transactions','user_id','users','id', 'SET NULL', 'SET NULL'); + + $this->addForeignKey('document_type_fields_link','document_type_id', 'document_types_lookup','id'); + $this->addForeignKey('document_type_fields_link','field_id','document_fields','id'); + + $this->addForeignKey('document_type_fieldsets_link','document_type_id', 'document_types_lookup','id'); + $this->addForeignKey('document_type_fieldsets_link','fieldset_id','fieldsets','id'); + + $this->addForeignKey('documents','creator_id','users','id', 'SET NULL', 'SET NULL'); + $this->addForeignKey('documents','folder_id','folders','id'); // we don't want this + $this->addForeignKey('documents','checked_out_user_id','users','id', 'SET NULL', 'SET NULL'); + $this->addForeignKey('documents','status_id','status_lookup','id'); + $this->addForeignKey('documents','permission_object_id','permission_objects','id'); + $this->addForeignKey('documents','permission_lookup_id','permission_lookups','id'); + $this->addForeignKey('documents','modified_user_id','users','id', 'SET NULL', 'SET NULL'); + $this->addForeignKey('documents','metadata_version_id','document_metadata_version','id'); + + $this->addForeignKey('download_files','document_id','documents','id'); + + $this->addForeignKey('field_behaviour_options','behaviour_id','field_behaviours','id'); + $this->addForeignKey('field_behaviour_options','field_id','document_fields','id'); + $this->addForeignKey('field_behaviour_options','instance_id','field_value_instances','id'); + + $this->addForeignKey('field_behaviours','field_id','document_fields','id'); + + $this->addForeignKey('field_orders','child_field_id','document_fields','id'); + $this->addForeignKey('field_orders','parent_field_id','document_fields','id'); + $this->addForeignKey('field_orders','fieldset_id','fieldsets','id'); + + $this->addForeignKey('field_value_instances','field_value_id','metadata_lookup','id'); // it is so.. strange ;) + $this->addForeignKey('field_value_instances','behaviour_id','field_behaviours','id'); + $this->addForeignKey('field_value_instances','field_id','document_fields','id'); + + $this->addForeignKey('fieldsets','master_field','document_fields','id'); + + $this->addForeignKey('folder_doctypes_link','folder_id','folders','id'); + $this->addForeignKey('folder_doctypes_link','document_type_id','document_types_lookup','id'); + + $this->addForeignKey('folder_searchable_text','folder_id','folders','id'); + + $this->addForeignKey('folder_subscriptions','user_id','users','id'); + $this->addForeignKey('folder_subscriptions','folder_id','folders','id'); + + $this->addForeignKey('folder_transactions','folder_id','folders','id', 'SET NULL', 'SET NULL'); + $this->addForeignKey('folder_transactions','user_id','users','id', 'SET NULL', 'SET NULL'); + + $this->addForeignKey('folder_workflow_map','folder_id', 'folders','id'); + $this->addForeignKey('folder_workflow_map','workflow_id', 'workflows','id'); + + $this->addForeignKey('folders','creator_id','users','id'); + $this->addForeignKey('folders','permission_object_id','permission_objects','id'); + $this->addForeignKey('folders','permission_lookup_id','permission_lookups','id'); +// $this->addForeignKey('folders','parent_id','folders','id'); // cant do this because of root that is 0... need to make it null! + + $this->addForeignKey('folders_users_roles_link','user_id','users','id'); + $this->addForeignKey('folders_users_roles_link','document_id','documents','id'); + + $this->addForeignKey('groups_groups_link','parent_group_id','groups_lookup','id'); + $this->addForeignKey('groups_groups_link','member_group_id','groups_lookup','id'); + + $this->addForeignKey('groups_lookup','unit_id', 'units_lookup','id'); + + $this->addForeignKey('index_files','document_id','documents','id'); + $this->addForeignKey('index_files','user_id','users','id'); + + $this->addForeignKey('metadata_lookup','document_field_id','document_fields','id'); +// $this->addForeignKey('metadata_lookup','treeorg_parent','??','id'); + + $this->addForeignKey('metadata_lookup_tree','document_field_id', 'document_fields','id'); +// $this->addForeignKey('metadata_lookup_tree','metadata_lookup_tree_parent', '??','id'); + + $this->addForeignKey('mime_types','mime_document_id','mime_documents','id'); + + $this->addForeignKey('news','image_mime_type_id','mime_types','id'); + + $this->addForeignKey('notifications','user_id', 'users','id'); + + $this->addForeignKey('permission_assignments','permission_id', 'permissions','id'); + $this->addForeignKey('permission_assignments','permission_object_id','permission_objects','id'); // duplicate + $this->addForeignKey('permission_assignments','permission_descriptor_id','permission_descriptors','id'); + + $this->addForeignKey('permission_descriptor_groups','descriptor_id','permission_descriptors','id'); + $this->addForeignKey('permission_descriptor_groups','group_id','groups_lookup','id'); + + $this->addForeignKey('permission_descriptor_roles','descriptor_id','permission_descriptors','id'); + $this->addForeignKey('permission_descriptor_roles','role_id','roles','id'); + + $this->addForeignKey('permission_descriptor_users','descriptor_id','permission_descriptors','id'); + $this->addForeignKey('permission_descriptor_users','user_id','users','id'); + + $this->addForeignKey('permission_dynamic_assignments','dynamic_condition_id','permission_dynamic_conditions','id'); + $this->addForeignKey('permission_dynamic_assignments','permission_id','permissions','id'); + + $this->addForeignKey('permission_dynamic_conditions','permission_object_id','permission_objects','id'); + $this->addForeignKey('permission_dynamic_conditions','group_id','groups_lookup','id'); + $this->addForeignKey('permission_dynamic_conditions','condition_id','saved_searches','id'); + + $this->addForeignKey('permission_lookup_assignments','permission_id','permissions','id'); + $this->addForeignKey('permission_lookup_assignments','permission_lookup_id','permission_lookups','id'); // duplicate + $this->addForeignKey('permission_lookup_assignments','permission_descriptor_id','permission_descriptors','id'); + + $this->addForeignKey('plugin_rss','user_id','users','id'); + + $this->addForeignKey('quicklinks','user_id','users','id'); + + $this->addForeignKey('role_allocations','folder_id','folders','id'); + $this->addForeignKey('role_allocations','role_id', 'roles','id'); + $this->addForeignKey('role_allocations','permission_descriptor_id','permission_descriptors','id'); + + $this->addForeignKey('saved_searches','user_id','users','id'); + + $this->addForeignKey('search_document_user_link','document_id','documents','id'); + $this->addForeignKey('search_document_user_link','user_id','users','id'); + + $this->addForeignKey('search_saved','user_id','users','id'); + $this->addForeignKey('search_saved_events','document_id','documents','id'); + + $this->addForeignKey('time_period','time_unit_id','time_unit_lookup','id'); + + $this->addForeignKey('type_workflow_map','document_type_id','document_types_lookup','id'); + $this->addForeignKey('type_workflow_map','workflow_id','workflows','id'); + + $this->addForeignKey('units_lookup','folder_id','folders','id'); + + $this->addForeignKey('units_organisations_link','unit_id','units_lookup','id'); + $this->addForeignKey('units_organisations_link','organisation_id','organisations_lookup','id'); + + $this->addForeignKey('uploaded_files','userid','users','id'); + $this->addForeignKey('uploaded_files','document_id','documents','id'); + + $this->addForeignKey('user_history','user_id','users','id'); + + $this->addForeignKey('users','authentication_source_id','authentication_sources','id'); + + $this->addForeignKey('users_groups_link', 'user_id','users','id'); + $this->addForeignKey('users_groups_link', 'group_id','groups_lookup', 'id'); + + $this->addForeignKey('workflow_documents','document_id', 'documents','id'); + $this->addForeignKey('workflow_documents','workflow_id', 'workflows','id'); + $this->addForeignKey('workflow_documents','state_id','workflow_states','id'); + + $this->addForeignKey('workflow_state_actions','state_id','workflow_states','id'); + + $this->addForeignKey('workflow_state_disabled_actions','state_id','workflow_states','id'); + + $this->addForeignKey('workflow_state_permission_assignments','permission_id','permissions','id'); + $this->addForeignKey('workflow_state_permission_assignments','permission_descriptor_id','permission_descriptors','id'); + $this->addForeignKey('workflow_state_permission_assignments','workflow_state_id','workflow_states','id'); + + $this->addForeignKey('workflow_state_transitions','state_id','workflow_states','id'); + $this->addForeignKey('workflow_state_transitions','transition_id','workflow_transitions','id'); + + $this->addForeignKey('workflow_states','workflow_id', 'workflows','id'); + $this->addForeignKey('workflow_states','inform_descriptor_id', 'permission_descriptors','id'); + + $this->addForeignKey('workflow_transitions','workflow_id','workflows','id'); + $this->addForeignKey('workflow_transitions','target_state_id','workflow_states','id'); + $this->addForeignKey('workflow_transitions','guard_permission_id','permissions','id'); + $this->addForeignKey('workflow_transitions','guard_condition_id','saved_searches','id'); + $this->addForeignKey('workflow_transitions','guard_group_id','groups_lookup','id'); + $this->addForeignKey('workflow_transitions','guard_role_id','roles','id'); + + $this->addForeignKey('workflow_trigger_instances','workflow_transition_id','workflow_transitions','id'); + + $this->addForeignKey('workflows','start_state_id','workflow_states','id'); + + } + + function removeDuplicateIndexes() + { + foreach($this->primary as $table=>$key) + { + $this->dropIndex($table,$key); + } + + } + function addOtherIndexes() + { + $this->addIndex('active_sessions', 'session_id'); + $this->addIndex('authentication_sources','namespace'); + + $this->addIndex('column_entries','view_namespace'); + + $this->addIndex('comment_searchable_text', 'body', 'FULLTEXT'); + + + $this->addIndex('dashlet_disables','dashlet_namespace'); + $this->addIndex('document_content_version','storage_path'); + + $this->addIndex('document_metadata_version','version_created'); + $this->addIndex('document_role_allocations', array('document_id', 'role_id')); + + $this->addIndex('document_searchable_text','document_text', 'FULLTEXT'); + + $this->addIndex('document_text','document_text', 'FULLTEXT'); + $this->addIndex('document_transaction_text','document_text', 'FULLTEXT'); + + $this->addIndex('document_transaction_types_lookup','namespace', 'UNIQUE'); + + $this->addIndex('document_transactions','session_id'); + + $this->addIndex('document_types_lookup','name'); + //$this->addIndex('document_types_lookup','disabled'); ? used + + $this->addIndex('documents','created'); + + $this->addIndex('field_behaviour_options',array('behaviour_id','field_id')); + + $this->addIndex('field_behaviours','name'); + + $this->addIndex('fieldsets','is_generic'); + $this->addIndex('fieldsets','is_complete'); + $this->addIndex('fieldsets','is_system'); + + $this->addIndex('folder_searchable_text','folder_text' ,'FULLTEXT'); + + $this->addIndex('folder_transactions','session_id'); + + $this->addIndex('folders','name'); + $this->addIndex('folders', array('parent_id','name')); + + $this->addIndex('groups_lookup','name'); + $this->addIndex('groups_lookup', array('authentication_source_id','authentication_details_s1')); + + $this->addIndex('interceptor_instances','interceptor_namespace'); // unique? + + $this->addIndex('metadata_lookup','disabled'); + //$this->addNewIndex('metadata_lookup','is_stuck'); don't think this is used anywhere.... + + $this->addIndex('metadata_lookup_tree','metadata_lookup_tree_parent'); + + $this->addIndex('mime_types','filetypes'); // should be unique... + $this->addIndex('mime_types','mimetypes'); + + $this->addIndex('notifications','data_int_1'); // document id seems to be stored in this. used by clearnotifications. +// $this->addIndex('notifications','type'); // don't think this is used + + $this->addIndex('organisations_lookup','name', 'UNIQUE'); + + $this->addIndex('permission_assignments', array('permission_object_id','permission_id'), 'UNIQUE'); // note change of order +// $this->dropIndex('permission_assignments','permission_object_id'); // duplicate + + //$this->dropIndex('permission_descriptor_groups','descriptor_id'); // in primary key + $this->addIndex('permission_descriptor_groups','group_id'); + + //$this->dropIndex('permission_descriptor_roles','descriptor_id'); // in primary key + $this->addIndex('permission_descriptor_roles','role_id'); + + //$this->dropIndex('permission_descriptor_users','descriptor_id'); // in primary + $this->addIndex('permission_descriptor_users','user_id'); + + $this->addIndex('permission_descriptors','descriptor'); + + $this->addIndex('permission_lookup_assignments', array('permission_lookup_id', 'permission_id')); + //$this->dropIndex('permission_lookup_assignments','permission_lookup_id'); // in composite + + $this->addIndex('permissions','name', 'UNIQUE'); + + $this->addIndex('plugins','namespace','UNIQUE'); + $this->addIndex('plugins','disabled'); + + $this->addIndex('quicklinks','target_id'); + + $this->addIndex('roles','name','UNIQUE'); + $this->addIndex('saved_searches','namespace','UNIQUE'); + + $this->addIndex('system_settings','name', 'UNIQUE'); + + $this->addIndex('units_lookup','name' ,'UNIQUE'); + $this->dropIndex('units_lookup','folder_id'); + $this->addIndex('units_lookup','folder_id' ,'UNIQUE'); + + $this->addIndex('upgrades','descriptor'); + $this->addIndex('upgrades','parent'); + + $this->addIndex('user_history','action_namespace'); + $this->addIndex('user_history','datetime'); + $this->addIndex('user_history','session_id'); + + $this->addIndex('user_history_documents', array('user_id','document_id')); + //$this->dropIndex('user_history_documents', 'user_id'); // duplicate + + $this->addIndex('user_history_folders', array('user_id','folder_id')); + //$this->dropIndex('user_history_folders', 'user_id'); // duplicate + + $this->addIndex('users','username' ,'UNIQUE'); + $this->addIndex('users','authentication_source_id'); + //$this->addNewIndex('users','authentication_details_b1'); + //$this->addNewIndex('users','authentication_details_b2'); + $this->addIndex('users','last_login'); + $this->addIndex('users','disabled'); + + $this->addIndex('workflow_states','name'); + $this->addIndex('workflow_states','inform_descriptor_id'); //? + + $this->addIndex('workflow_transitions',array('workflow_id','name'), 'UNIQUE'); + //$this->dropIndex('workflow_transitions','workflow_id'); // duplicate + $this->addIndex('workflow_transitions','name'); + $this->addIndex('workflow_transitions','guard_permission_id'); //? + + $this->addIndex('workflow_trigger_instances','namespace'); + + $this->addIndex('workflows','name'); + + + } + + function applyPostFixes() + { + + } + + function dropIndex($table, $field) + { + if (!is_array($fields)) $field = array($field); + $field = implode('_', $field); + $sql = "alter table $table drop index $field"; + $this->_exec($sql); + } + + function addIndex($table, $fields, $type='') + { + if (!is_array($fields)) $fields = array($fields); + $index = implode('_', $fields); + //$index = str_replace('_id','',$index); + $fields = implode(',',$fields); + $sql = "alter table $table add $type index $index ($fields) "; + $this->_exec($sql); + } + + function addForeignKey($table, $field, $othertable, $otherfield, $ondelete='cascade', $onupdate='cascade') + { + $sql = "alter table $table add foreign key ($field) references $othertable ($otherfield) "; + if ($ondelete != '') + $sql .= " on delete $ondelete"; + if ($onupdate != '') + $sql .= " on update $onupdate"; + $this->_exec($sql); + } + + function addPrimaryKeys() + { + $this->addPrimaryKey('active_sessions', 'id'); + $this->addPrimaryKey('archive_restoration_request','id'); + $this->addPrimaryKey('archiving_settings','id'); + $this->addPrimaryKey('archiving_type_lookup','id'); + $this->addPrimaryKey('authentication_sources','id'); + $this->addPrimaryKey('baobab_keys','id'); + $this->addPrimaryKey('baobab_user_keys','id'); + $this->addPrimaryKey('column_entries','id'); + $this->addPrimaryKey('comment_searchable_text','comment_id'); + $this->addPrimaryKey('dashlet_disables','id'); + $this->addPrimaryKey('data_types','id'); + $this->addPrimaryKey('discussion_comments','id'); + $this->addPrimaryKey('discussion_threads','id'); + $this->addPrimaryKey('document_archiving_link','id'); + $this->addPrimaryKey('document_content_version','id'); + $this->addPrimaryKey('document_fields','id'); + $this->addPrimaryKey('document_fields_link','id'); + $this->addPrimaryKey('document_incomplete','id'); + $this->addPrimaryKey('document_link','id'); + $this->addPrimaryKey('document_link_types','id'); + $this->addPrimaryKey('document_metadata_version','id'); + $this->addPrimaryKey('document_role_allocations','id'); + $this->addPrimaryKey('document_subscriptions','id'); + $this->addPrimaryKey('document_tags',array('document_id','tag_id')); + $this->addPrimaryKey('document_text', 'document_id'); + $this->addPrimaryKey('document_transaction_types_lookup', 'id'); + $this->addPrimaryKey('document_transaction_text', 'document_id'); + $this->addPrimaryKey('document_transaction_types_lookup','id'); + $this->addPrimaryKey('document_transactions','id'); + $this->addPrimaryKey('document_type_fields_link','id'); + $this->addPrimaryKey('document_type_fieldsets_link','id'); + $this->addPrimaryKey('document_types_lookup','id'); + $this->addPrimaryKey('documents','id'); + $this->addPrimaryKey('download_files',array('document_id','session')); + $this->addPrimaryKey('field_behaviours','id'); + $this->addPrimaryKey('field_value_instances','id'); + $this->addPrimaryKey('fieldsets','id'); + $this->addPrimaryKey('folder_doctypes_link','id'); + $this->addPrimaryKey('folder_searchable_text','folder_id'); + $this->addPrimaryKey('folder_subscriptions','id'); + $this->addPrimaryKey('folder_transactions','id'); + $this->addPrimaryKey('folder_workflow_map','folder_id'); + $this->addPrimaryKey('folders','id'); + $this->addPrimaryKey('folders_users_roles_link','id'); + $this->addPrimaryKey('groups_groups_link','id'); + $this->addPrimaryKey('groups_lookup','id'); + $this->addPrimaryKey('help','id'); + $this->addPrimaryKey('help_replacement','id'); + $this->addPrimaryKey('interceptor_instances','id'); + $this->addPrimaryKey('links','id'); + $this->addPrimaryKey('metadata_lookup','id'); + $this->addPrimaryKey('metadata_lookup_tree','id'); + $this->addPrimaryKey('mime_documents','id'); + $this->addPrimaryKey('mime_types','id'); + $this->addPrimaryKey('news','id'); + $this->addPrimaryKey('notifications','id'); + $this->addPrimaryKey('organisations_lookup','id'); + $this->addPrimaryKey('permission_assignments','id'); + $this->addPrimaryKey('permission_descriptor_groups', array('descriptor_id','group_id')); + $this->addPrimaryKey('permission_descriptor_roles', array('descriptor_id','role_id')); + $this->addPrimaryKey('permission_descriptor_users', array('descriptor_id','user_id')); + $this->addPrimaryKey('permission_descriptors','id'); + $this->addPrimaryKey('permission_dynamic_conditions','id'); + $this->addPrimaryKey('permission_lookup_assignments','id'); + $this->addPrimaryKey('permission_lookups','id'); + $this->addPrimaryKey('permission_objects','id'); + $this->addPrimaryKey('permissions','id'); + $this->addPrimaryKey('plugin_rss','id'); + $this->addPrimaryKey('plugins','id'); + $this->addPrimaryKey('quicklinks','id'); + $this->addPrimaryKey('role_allocations','id'); + $this->addPrimaryKey('roles','id'); + $this->addPrimaryKey('saved_searches','id'); + $this->addPrimaryKey('scheduler_tasks','id'); + $this->addPrimaryKey('search_ranking',array('groupname','itemname')); + $this->addPrimaryKey('search_saved','id'); + $this->addPrimaryKey('search_saved_events','document_id'); + $this->addPrimaryKey('status_lookup','id'); + $this->addPrimaryKey('system_settings','id'); + $this->addPrimaryKey('tag_words','id'); + $this->addPrimaryKey('time_period','id'); + $this->addPrimaryKey('time_unit_lookup','id'); + $this->addPrimaryKey('trigger_selection','event_ns'); + $this->addPrimaryKey('type_workflow_map','document_type_id'); + $this->addPrimaryKey('units_lookup','id'); + $this->addPrimaryKey('units_organisations_link','id'); + $this->addPrimaryKey('upgrades','id'); + $this->addPrimaryKey('uploaded_files','tempfilename'); + $this->addPrimaryKey('user_history','id'); + $this->addPrimaryKey('user_history_documents','id'); + $this->addPrimaryKey('user_history_folders','id'); + $this->addPrimaryKey('users','id'); + $this->addPrimaryKey('users_groups_link','id'); + $this->addPrimaryKey('workflow_actions','workflow_id'); + $this->addPrimaryKey('workflow_documents','document_id'); + $this->addPrimaryKey('workflow_state_permission_assignments','id'); + $this->addPrimaryKey('workflow_states','id'); + $this->addPrimaryKey('workflow_transitions','id'); + $this->addPrimaryKey('workflow_trigger_instances','id'); + $this->addPrimaryKey('workflows','id'); + } + + function addPrimaryKey($table, $primarykey) + { + if (is_array($primarykey)) + { + $primarykey = implode(',', $primarykey); + } + + $sql="alter table $table add primary key ($primarykey)"; + $this->_exec($sql, false); + + if (strpos($primarykey,',') === false) + { + $this->primary[$table] = $primarykey; + $sql="alter table $table add unique key ($primarykey)"; + $this->_exec($sql); + } + } + + function dropIndexes() + { + $result = DBUtil::getResultArray("show tables"); + $tables=array(); + + foreach($result as $table) + { + $keys = array_keys($table); + + $tablename = $table[$keys[0]]; + if (substr($tablename,0,5) == 'zseq_') + { + continue; + } + + $stmt = DBUtil::getResultArray("show create table $tablename"); + + $keys = array_keys($stmt[0]); + + $sql = $stmt[0][$keys[1]]; + + $table = array('fks'=>array(), 'pk'=>array(), 'keys'=>array()); + $lines = explode("\n", $sql); + foreach($lines as $line) + { + $line = trim($line); + if (strpos($line, 'PRIMARY KEY') === 0) + { + preg_match('(\`([^\`])*\`)',$line, $params); + $primaryKey = explode(',', $params[0]); + foreach($primaryKey as $value) + { + $fieldname = substr($value,1,-1); + $table['pk'][] = $fieldname; + } + continue; + } + elseif (strpos($line, 'CONSTRAINT') === 0) + { + preg_match_all('(\`([^\`])*\`)',$line, $params); + + $fieldname = substr($params[0][1],1,-1); + + $table['fks'][$fieldname] = array( + 'constraint'=>substr($params[0][0],1,-1), + 'table'=>substr($params[0][2],1,-1), + 'field'=>substr($params[0][3],1,-1) + ); + continue; + } + elseif (strpos($line, 'KEY') !== false) + { + preg_match_all('(\`([^\`])*\`)',$line, $params); + $fieldname = substr($params[0][1],1,-1); + $key = substr($params[0][0],1,-1); + $table['keys'][$fieldname] = array('name'=>$key, 'unique'=>false); + if (strpos($line, 'UNIQUE KEY') !== false) + { + if (count($params[0]) == 2) + { + $table['keys'][$fieldname]['unique']=true; + } + } + continue; + } + } + + $tables[$tablename]= $table; + } + + $dropped = 0; + + // drop foreign keys + foreach($tables as $tablename=>$table) + { + foreach($table['fks'] as $fieldname=>$constraint) + { + $name = $constraint['constraint']; + $table = $constraint['table']; + $field = $constraint['field']; + $sql = "ALTER TABLE $tablename DROP FOREIGN KEY $name;"; + if ($this->_exec($sql)) $dropped++; + } + } + + // drop primary keys + foreach($tables as $tablename=>$table) + { + foreach($table['pk'] as $fieldname) + { + $sql = "ALTER TABLE $tablename DROP primary key;"; + if ($this->_exec($sql,false)) $dropped++; + break; + } + } + + // drop normal indexes + + foreach($tables as $tablename=>$table) + { + foreach($table['keys'] as $fieldname=>$keyinfo) + { + $keyname = $keyinfo['name']; + $sql = "ALTER TABLE $tablename DROP key $keyname;"; + if ($this->_exec($sql)) $dropped++; + break; + } + } + + + return $dropped; + } + + function _exec($sql, $report = true) + { + print "Action: $sql"; + $this->start(); + $rs = DBUtil::runQuery($sql); + print " - " . $this->end() . "\n"; + if (PEAR::isError($rs)) + { + if ($report) print "* " . $rs->getMessage() . "\n"; + return false; + } + return true; + } + +} + + +?> \ No newline at end of file diff --git a/config/dmsDefaults.php b/config/dmsDefaults.php index 392189d..54e8c1b 100644 --- a/config/dmsDefaults.php +++ b/config/dmsDefaults.php @@ -27,7 +27,7 @@ * Portions created by The Jam Warehouse Software (Pty) Ltd are Copyright * (C) 2007 The Jam Warehouse Software (Pty) Ltd; * All Rights Reserved. - * Contributor( s): ______________________________________ + * Contributor( s): Guenter Roeck______________________________________ * */ @@ -348,6 +348,10 @@ class KTInit { if ($i === false) { break; } + if ($rootUrl) + { + $rootUrl .= '/'; + } $rootUrl .= substr($urlpath, 0, $i); $urlpath = substr($urlpath, $i + 1); } diff --git a/ktwsapi/delphi/TODO.txt b/ktwsapi/delphi/TODO.txt deleted file mode 100644 index e69de29..0000000 --- a/ktwsapi/delphi/TODO.txt +++ /dev/null diff --git a/ktwsapi/delphi/doc/KTWSAPI.chm b/ktwsapi/delphi/doc/KTWSAPI.chm new file mode 100644 index 0000000..a64e7ea --- /dev/null +++ b/ktwsapi/delphi/doc/KTWSAPI.chm diff --git a/ktwsapi/delphi/examples/KTWSAPIExamples.bdsproj b/ktwsapi/delphi/examples/KTWSAPIExamples.bdsproj new file mode 100644 index 0000000..188af84 --- /dev/null +++ b/ktwsapi/delphi/examples/KTWSAPIExamples.bdsproj @@ -0,0 +1,194 @@ + + + + + + + + + + + + KTWSAPIExamples.dpr + + + 7.0 + + + 8 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 1 + 1 + 1 + True + True + WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; + + False + + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + False + False + False + True + True + True + True + True + True + + + + 0 + 0 + False + 1 + False + False + False + 16384 + 1048576 + 4194304 + + + + + + + + + + + + False + + + + + + False + + + True + False + + + + $00000000 + + + + False + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 1044 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + RemObjects Everwood for Delphi + RemObjects SDK - Core Library + RemObjects SDK - WebBroker Library + RemObjects SDK - RODXSock Library + RemObjects SDK - BPDX Library + RemObjects SDK - DataSnap Integration Pack + RemObjects Pascal Script - Core Package + RemObjects Pascal Script - RemObjects SDK 3.0 Integration + RemObjects SDK - Indy Library + RemObjects SDK - IDE Integration for Win32 + RemObjects Data Abstract - Core Library + RemObjects Data Abstract - IDE Package + RemObjects Data Abstract - ADOExpress/dbGo Driver + RemObjects Data Abstract - InterBase Express Driver + RemObjects Data Abstract - dbExpress Driver + RemObjects Data Abstract - Scripting Integration Library + + + + + diff --git a/ktwsapi/delphi/examples/KTWSAPIExamples.dpr b/ktwsapi/delphi/examples/KTWSAPIExamples.dpr new file mode 100644 index 0000000..abacfde --- /dev/null +++ b/ktwsapi/delphi/examples/KTWSAPIExamples.dpr @@ -0,0 +1,55 @@ +{ + Copyright (c) 2007, The Jam Warehouse Software (Pty) Ltd. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + i) Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + ii) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + iii) Neither the name of the The Jam Warehouse Software (Pty) Ltd nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES ( INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ( INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +} + +{* + This is a Delphi port of the php api for KnowledgeTree WebService. + + @Author Bjarte Kalstveit Vebjørnsen + @Version 1.0 BKV 24.09.2007 Initial revision +*} + + +program KTWSAPIExamples; + +uses + Forms, + uFolderContentExample in 'uFolderContentExample.pas' {FolderContentExample}, + uwebservice in '..\uwebservice.pas', + uktwsapi in '..\uktwsapi.pas', + uPHPserialize in '..\uPHPserialize.pas'; + +{$R *.res} + +begin + Application.Initialize; + Application.CreateForm(TFolderContentExample, FolderContentExample); + Application.Run; +end. + diff --git a/ktwsapi/delphi/examples/KTWSAPIExamples.res b/ktwsapi/delphi/examples/KTWSAPIExamples.res new file mode 100644 index 0000000..7eb23e4 --- /dev/null +++ b/ktwsapi/delphi/examples/KTWSAPIExamples.res diff --git a/ktwsapi/delphi/examples/uFolderContentExample.dfm b/ktwsapi/delphi/examples/uFolderContentExample.dfm new file mode 100644 index 0000000..51a0ed1 --- /dev/null +++ b/ktwsapi/delphi/examples/uFolderContentExample.dfm @@ -0,0 +1,183 @@ +object FolderContentExample: TFolderContentExample + Left = 0 + Top = 0 + Caption = 'FolderContentExample' + ClientHeight = 538 + ClientWidth = 219 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + OldCreateOrder = False + PixelsPerInch = 96 + TextHeight = 13 + object tvFolderList: TTreeView + AlignWithMargins = True + Left = 3 + Top = 34 + Width = 213 + Height = 501 + Align = alClient + Images = ImageList4 + Indent = 19 + TabOrder = 0 + OnCollapsed = tvFolderListCollapsed + OnExpanded = tvFolderListExpanded + end + object Button1: TButton + AlignWithMargins = True + Left = 3 + Top = 3 + Width = 213 + Height = 25 + Align = alTop + Caption = 'Populate folders' + TabOrder = 1 + OnClick = Button1Click + end + object ImageList4: TImageList + Left = 8 + Top = 496 + Bitmap = { + 494C010102000400040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 + 0000000000003600000028000000400000001000000001002000000000000010 + 00000000000000000000000000000000000000000000078DBE00078DBE00078D + BE00078DBE00078DBE00078DBE00078DBE00078DBE00078DBE00078DBE00078D + BE00078DBE00078DBE00000000000000000000000000078DBE00078DBE00078D + BE00078DBE00078DBE00078DBE00078DBE00078DBE00078DBE00078DBE00078D + BE00078DBE000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000078DBE0063CBF800078DBE00A3E1 + FB0066CDF90065CDF80065CDF90065CDF90065CDF80065CDF90065CDF80066CD + F8003AADD800ACE7F500078DBE0000000000078DBE0025A1D10071C6E80084D7 + FA0066CDF90065CDF90065CDF90065CDF90065CDF80065CDF90065CDF80066CE + F9003AADD8001999C90000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000078DBE006AD1F900078DBE00A8E5 + FC006FD4FA006FD4F9006ED4FA006FD4F9006FD4FA006FD4FA006FD4FA006ED4 + F9003EB1D900B1EAF500078DBE0000000000078DBE004CBCE70039A8D100A0E2 + FB006FD4FA006FD4F9006ED4FA006FD4F9006FD4FA006FD4FA006FD4FA006ED4 + F9003EB1D900C9F0F300078DBE00000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000078DBE0072D6FA00078DBE00AEEA + FC0079DCFB0079DCFB0079DCFB0079DCFB0079DCFB007ADCFB0079DCFA0079DC + FA0044B5D900B6EEF600078DBE0000000000078DBE0072D6FA00078DBE00AEE9 + FC0079DCFB0079DCFB0079DCFB0079DCFB0079DCFB007ADCFB0079DCFA0079DC + FA0044B5D900C9F0F300078DBE00000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000078DBE0079DDFB00078DBE00B5EE + FD0083E4FB0084E4FB0083E4FC0083E4FC0084E4FC0083E4FC0083E4FB0084E5 + FC0048B9DA00BBF2F600078DBE0000000000078DBE0079DDFB001899C7009ADF + F30092E7FC0084E4FB0083E4FC0083E4FC0084E4FC0083E4FC0083E4FB0084E5 + FC0048B9DA00C9F0F3001496C400000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000078DBE0082E3FC00078DBE00BAF3 + FD008DEBFC008DEBFC008DEBFC008DEBFD008DEBFD008DEBFC008DEBFD008DEB + FC004CBBDA00BEF4F700078DBE0000000000078DBE0082E3FC0043B7DC0065C2 + E000ABF0FC008DEBFC008DEBFC008DEBFD008DEBFD008DEBFC008DEBFD008DEB + FC004CBBDA00C9F0F300C9F0F300078DBE000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000078DBE008AEAFC00078DBE00FFFF + FF00C9F7FE00C8F7FE00C9F7FE00C9F7FE00C9F7FE00C8F7FE00C9F7FE00C8F7 + FE009BD5E700DEF9FB00078DBE0000000000078DBE008AEAFC0077DCF300219C + C700FEFFFF00C8F7FD00C9F7FD00C9F7FD00C9F7FE00C8F7FE00C9F7FD00C8F7 + FE009BD5E600EAFEFE00D2F3F800078DBE000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000078DBE0093F0FE00078DBE00078D + BE00078DBE00078DBE00078DBE00078DBE00078DBE00078DBE00078DBE00078D + BE00078DBE00078DBE00078DBE0000000000078DBE0093F0FE0093F0FD001697 + C500078DBE00078DBE00078DBE00078DBE00078DBE00078DBE00078DBE00078D + BE00078DBE00078DBE00078DBE00078DBE000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000078DBE009BF5FE009AF6FE009AF6 + FE009BF5FD009BF6FE009AF6FE009BF5FE009AF6FD009BF5FE009AF6FE009AF6 + FE000989BA00000000000000000000000000078DBE009BF5FE009AF6FE009AF6 + FE009BF5FD009BF6FE009AF6FE009BF5FE009AF6FD009BF5FE009AF6FE009AF6 + FE000989BA000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000078DBE00FEFEFE00A0FBFF00A0FB + FE00A0FBFE00A1FAFE00A1FBFE00A0FAFE00A1FBFE00A1FBFF00A0FBFF00A1FB + FF000989BA00000000000000000000000000078DBE00FEFEFE00A0FBFF00A0FB + FE00A0FBFE00A1FAFE00A1FBFE00A0FAFE00A1FBFE00A1FBFF00A0FBFF00A1FB + FF000989BA000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000078DBE00FEFEFE00A5FE + FF00A5FEFF00A5FEFF00078DBE00078DBE00078DBE00078DBE00078DBE00078D + BE000000000000000000000000000000000000000000078DBE00FEFEFE00A5FE + FF00A5FEFF00A5FEFF00078DBE00078DBE00078DBE00078DBE00078DBE00078D + BE00000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000078DBE00078D + BE00078DBE00078DBE0000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000078DBE00078D + BE00078DBE00078DBE0000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000424D3E000000000000003E000000 + 2800000040000000100000000100010000000000800000000000000000000000 + 000000000000000000000000FFFFFF0080038007000000000001000300000000 + 0001000100000000000100010000000000010001000000000001000000000000 + 0001000000000000000100000000000000070007000000000007000700000000 + 800F800F00000000C3FFC3FF00000000FFFFFFFF00000000FFFFFFFF00000000 + FFFFFFFF00000000FFFFFFFF0000000000000000000000000000000000000000 + 000000000000} + end +end diff --git a/ktwsapi/delphi/examples/uFolderContentExample.pas b/ktwsapi/delphi/examples/uFolderContentExample.pas new file mode 100644 index 0000000..728495c --- /dev/null +++ b/ktwsapi/delphi/examples/uFolderContentExample.pas @@ -0,0 +1,108 @@ +unit uFolderContentExample; + +interface + +uses + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, + Dialogs, uKtwsapi, uWebService, ImgList, ComCtrls, StdCtrls; + +type + TFolderContentExample = class(TForm) + tvFolderList: TTreeView; + ImageList4: TImageList; + Button1: TButton; + procedure Button1Click(Sender: TObject); + procedure tvFolderListCollapsed(Sender: TObject; Node: TTreeNode); + procedure tvFolderListExpanded(Sender: TObject; Node: TTreeNode); + private + { Private declarations } + FIsPopulating: Boolean; + procedure PopulateTreeView(items: kt_folder_items; + parent: TTreeNode; tv: TTreeView); + public + { Public declarations } + end; + +var + FolderContentExample: TFolderContentExample; + UserName, Password: String; + +implementation + +{$R *.dfm} + +procedure TFolderContentExample.Button1Click(Sender: TObject); +var + ktapi: TKTWSAPI; + folder: TKTWSAPI_Folder; + contents: kt_folder_contents; +begin + if FIsPopulating then Exit; + + Screen.Cursor := crHourglass; + + FIsPopulating := True; + ktapi := TKTWSAPI.Create; + try + ktapi.SetDownloadPath(ExtractFileDir(Application.ExeName)); + ktapi.StartSession(UserName,Password); + + folder:= ktapi.GetRootFolder; + try + contents := folder.GetListing(10); + try + PopulateTreeView(contents.items, nil, tvFolderList); + finally + contents.Free; + end; + finally + folder.Free; + end; + + ktapi.Logout; + finally + ktapi.Free; + Screen.Cursor := crDefault; + FIsPopulating := False; + end; +end; + +procedure TFolderContentExample.PopulateTreeView(items: kt_folder_items; parent: TTreeNode; + tv: TTreeView); +var + I: Integer; + node: TTreeNode; + it: kt_folder_item; +begin + for I := 0 to Length(items) - 1 do + begin + it := items[i]; + if it.item_type <> 'F' then Continue; + node := tv.Items.AddChild(parent, it.title); + node.ImageIndex := 0; + node.Data := it; + if (Length(it.items) > 0) then + PopulateTreeView(it.items, node, tv); + end; +end; + +procedure TFolderContentExample.tvFolderListCollapsed(Sender: TObject; + Node: TTreeNode); +begin + Node.ImageIndex := 0; +end; + +procedure TFolderContentExample.tvFolderListExpanded(Sender: TObject; + Node: TTreeNode); +begin + Node.ImageIndex := 1; +end; + +initialization + UserName := 'xxxx'; + Password := 'xxxx'; + uktwsapi.KTWebServerUrl := 'http://ktdms.trunk'; + uktwsapi.KTWebServiceUrl := uktwsapi.KTWebServerUrl+'/ktwebservice/webservice.php?wsdl'; + uktwsapi.KTUploadUrl := uktwsapi.KTWebServerUrl+'/ktwebservice/upload.php'; + +end. diff --git a/ktwsapi/delphi/uPHPserialize.pas b/ktwsapi/delphi/uPHPserialize.pas new file mode 100644 index 0000000..38905c8 --- /dev/null +++ b/ktwsapi/delphi/uPHPserialize.pas @@ -0,0 +1,469 @@ +{ + Copyright (c) 2007, The Jam Warehouse Software (Pty) Ltd. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + i) Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + ii) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + iii) Neither the name of the The Jam Warehouse Software (Pty) Ltd nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES ( INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ( INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +} + +{* + A helper unit to unserialize a php serialized string + + Inspired by the various implementaions presented here + http://www.phpguru.org/static/PHP_Unserialize.html + + @Author Bjarte Kalstveit Vebjørnsen + @Version 1.0 BKV 24.09.2007 Initial revision + @Todo A complementary serializing function would be nice +*} + +unit uPHPSerialize; + +interface + +uses + Classes, SysUtils, Variants, ComCtrls; + +type + TPHPValue = class; + TPHPArray = class; + TPHPSerialize = class; + + /// a single hash element + TPHPHashElement = record + Key: TPHPValue; /// The Key part of the element + Value: TPHPValue; /// The Value part of the element + end; + + /// an array of hash elements + TPHPHashedElementArray = array of TPHPHashElement; + + /// Tries to replicate a php array by accessing values through strings + /// @Todo: Add support for numeric keys + TPHPArray = class + private + FElements: TPHPHashedElementArray; /// array of hash elements + function GetValue(Key: string): TPHPValue; overload; + function GetValue(Key: TPHPValue): TPHPValue; overload; + procedure SetValue(Key: TPHPValue; VValue: TPHPValue); overload; + function GetCount: Integer; + function Getempty: Boolean; + public + property Value[Key: string]: TPHPValue read GetValue; default; + property Value[Key: TPHPValue]: TPHPValue read GetValue write SetValue; default; + property Count: Integer read GetCount; + property Empty: Boolean read Getempty; + procedure Clear; + constructor Create; + destructor Destroy; override; + end; + + /// Tries to represent a PHP value of any type + TPHPValue = class + private + FObj: TObject; /// Holds value if it's an object or array + FValue: String; /// Holds value if it's something else + procedure Clear; + public + constructor Create(Value: TObject); overload; + constructor Create(Value: String); overload; + destructor Destroy; override; + function AsString: String; + function AsDouble: Double; + function AsInteger: Integer; + function AsObject: TObject; + function AsArray: TPHPArray; + function AsBoolean: Boolean; + end; + + /// Class for unserializing a php serialized string + TPHPSerialize = class + private + function GetLength(Data: String): Integer; + function GetIntLength(Value: Integer): Integer; + public + class function Unserialize(Data: String): TPHPValue; + function _Unserialize(var Data: String): TPHPValue; + end; + +implementation + +{ TPHPSerialize } + +{* + Finds the length of they to the type + + @param string Data + @return integer +*} +function TPHPSerialize.GetLength(Data: String): Integer; +begin + Data := Copy(Data, 3, Length(Data)); + + Result := StrToIntDef(Copy(Data, 0, Pos(':', Data)-1), 0); +end; + +{* + Finds the lenght of the character-space the value occupies + + @param integer Value + @return Integer +*} +function TPHPSerialize.GetIntLength(Value: Integer): Integer; +begin + Result := Length(IntToStr(Value)); +end; + +{* + Helper function to use this class statically + + @param integer Value + @return Integer +*} +class function TPHPSerialize.Unserialize(Data: String): TPHPValue; +var + obj: TPHPSerialize; +begin + obj := TPHPSerialize.Create; + try + Result := obj._Unserialize(Data); + finally + obj.Free; + end; +end; + +{* + Recursing function for unserializing a string and creating a php value from it + + @see TPHPValue + @param Data String + @return TPHPValue +*} +function TPHPSerialize._Unserialize(var Data: String): TPHPValue; +var + I, Len: Integer; + Num: Double; + C: String; + Arr: TPHPArray; + Key, Value: TPHPValue; +begin + C := Copy(Data,0,1); + + if (C = 'a') then + begin + Len := GetLength(Data); + Data := Copy(Data, GetIntLength(Len) + 5, Length(Data) ); + + Arr := TPHPArray.Create; + for I := 0 to Len-1 do + begin + Key := _Unserialize(Data); + Value := _Unserialize(Data); + + Arr[Key] := Value; + end; + + Data := Copy(Data, Length(Data)); + Result := TPHPValue.Create(Arr); + + end else if (C = 's') then + begin + Len := GetLength(Data); + Result := TPHPValue.Create(Copy(Data, GetIntLength(Len) + 5, Len)); + Data := Copy(Data, GetIntLength(Len) + 7 + Len, Length(Data)); + end else if (C = 'i') or (C = 'd') then + begin + Num := StrToFloat(Copy(Data, 3, AnsiPos(';', Data)-3)); + Result := TPHPValue.Create(FloatToStr(Num)); + Data := Copy(Data, Length(FloatToStr(Num)) + 4, Length(Data)); + end else if (C = 'b') then + begin + Result := TPHPValue.Create(BoolToStr(Copy(Data, 3, 1) = '1')); + Data := Copy(Data, 4, Length(Data)); + end else if (C = 'O') or (C = 'r') or (C = 'C') or (C = 'R') + or (C = 'U') then + begin + raise Exception.Create('Unsupported PHP data type found!'); + end else if (C = 'N') then + begin + Result := TPHPValue.Create(nil); + Data := Copy(Data, 2, Length(Data)); + end else + begin + Result := TPHPValue.Create(nil); + Data := ''; + end; +end; + + +{ TPHPValue } + +{* + Returns value as boolan + + @return boolean value +*} +function TPHPValue.AsBoolean: Boolean; +begin + Result := StrToBool(FValue); +end; + +{* + Returns value as double + + @return double value +*} +function TPHPValue.AsDouble: Double; +begin + Result := StrToFloat(FValue); +end; + +{* + Returns value as an associative-array + + @return associative-array +*} +function TPHPValue.AsArray: TPHPArray; +begin + Result := nil; + Assert(Assigned(FObj)); + + if (FObj.ClassType = TPHPArray) then + Result := TPHPArray(FObj); +end; + +{* + Returns value as an integer + + @return integer value +*} +function TPHPValue.AsInteger: Integer; +begin + Result := StrToInt(FValue); +end; + +{* + Returns value as an object + + @return object value +*} +function TPHPValue.AsObject: TObject; +begin + Assert(Assigned(FObj)); + Result := FObj; +end; + +{* + Returns value as a string + + @return string value +*} +function TPHPValue.AsString: String; +begin + Result := FValue; +end; + +{* + Constructor + + @param Value Value to store +*} +constructor TPHPValue.Create(Value: String); +begin + Clear; + FValue := Value; +end; + +{* + Constructor + + @param Value Value to store +*} +constructor TPHPValue.Create(Value: TObject); +begin + Clear; + FObj := Value; +end; + +{* + Clears current value +*} +procedure TPHPValue.Clear; +begin + FValue := ''; + if Assigned(FObj) then FObj.Free; + FObj := nil; +end; + +{* + Destructor +*} +destructor TPHPValue.Destroy; +begin + Clear; + inherited; +end; + +{ TPHPArray } + + +{* + Clears whole array +*} +procedure TPHPArray.Clear; +var + i: Integer; +begin + for i := 0 to GetCount - 1 do + begin + FElements[i].Key.Free; + FElements[i].Key := nil; + FElements[i].Value.Free; + FElements[i].Value := nil; + end; + SetLength(FElements, 0); +end; + +{* + Constructor +*} +constructor TPHPArray.Create; +begin + inherited; + Clear; +end; + +{* + Destructor +*} +destructor TPHPArray.Destroy; +begin + Clear; + inherited; +end; + +{* + Returns the number of items in the array + + @return number of items +*} +function TPHPArray.GetCount: Integer; +begin + Result := Length(FElements); +end; + +{* + Checks if the array is empty + + @return true +*} +function TPHPArray.Getempty: Boolean; +begin + Result := Length(FElements) = 0; +end; + +{* + Fetch a phpvalue from the array + + @param Key Handle to phpvalue + @return handle to phpvalue +*} +function TPHPArray.GetValue(Key: TPHPValue): TPHPValue; +begin + Result := GetValue(Key.FValue); +end; + +{* + Fetch a phpvalue from the array + + @param Key Index to element + @return handle to phpvalue +*} +function TPHPArray.GetValue(Key: string): TPHPValue; +var + i: Integer; + r: Boolean; +begin + Result := nil; + i := 0; + r := False; + while (i < Length(FElements)) and (not r) do + begin + if AnsiUpperCase(FElements[i].key.AsString) = AnsiUpperCase(Key) then + begin + Result := FElements[i].Value; + r := True; + end; + i := i + 1; + end; +end; + +{* + Insert a phpvalue into the array + + @param Key Index to element + @return handle to phpvalue +*} +procedure TPHPArray.SetValue(Key, VValue: TPHPValue); +var + i, j: Integer; + r: Boolean; + E: TPHPHashedElementArray; +begin + if VValue <> nil then + begin + i := 0; + r := False; + while (i < Length(FElements)) and not r do + begin + if AnsiUpperCase(FElements[i].key.AsString) = AnsiUpperCase(Key.AsString) then + begin + FElements[i].Value := VValue; + r := True; + end; + i := i + 1; + end; + if not r then + begin + SetLength(FElements, Length(FElements) + 1); + FElements[Length(FElements) - 1].Key := Key; + FElements[Length(FElements) - 1].Value := Vvalue; + end; + end; + + SetLength(E, Length(FElements)); + for i := 0 to Length(FElements) - 1 do E[i] := FElements[i]; + SetLength(FElements, 0); + for i := 0 to Length(E) - 1 do if (E[i].Key.AsString <> '') + and (E[i].Value <> nil) then + begin + j := Length(FElements); + setlength(FElements, j + 1); + FElements[j] := E[i]; + end; +end; + +end. + diff --git a/ktwsapi/delphi/uktwsapi.pas b/ktwsapi/delphi/uktwsapi.pas new file mode 100644 index 0000000..8e8e88d --- /dev/null +++ b/ktwsapi/delphi/uktwsapi.pas @@ -0,0 +1,1630 @@ +{ + Copyright (c) 2007, The Jam Warehouse Software (Pty) Ltd. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + i) Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + ii) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + iii) Neither the name of the The Jam Warehouse Software (Pty) Ltd nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES ( INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ( INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +} + +{* + This is a Delphi port of the php api for KnowledgeTree WebService. + + @Author Bjarte Kalstveit Vebjørnsen + @Version 1.0 BKV 24.09.2007 Initial revision +*} + +unit uktwsapi; + +interface + +uses + Classes, SysUtils, SOAPHTTPClient, uwebservice; + +type + + /// Base exception class + EKTWSAPI_Exception = class(Exception); + + TKTWSAPI_FolderItem = class; + TKTWSAPI_Folder = class; + TKTWSAPI_Document = class; + TKTWSAPI = class; + + /// Base class for documents and folders + TKTWSAPI_FolderItem = class(TObject) + private + FKTAPI: TKTWSAPI; /// Handle to KTAPI object + FParentId: Integer; /// Id of parent folder + + function _GetFileSize(FileName: WideString): WideString; + function _UploadFile(FileName, Action: WideString; DocumentId: Integer = 0): WideString; + function _DownloadFile(Url, LocalPath, FileName: WideString): Boolean; + function _SaveBase64StringAsFile(Base64String, LocalPath, FileName: WideString): Boolean; + function _LoadFileAsBase64String(FileName: WideString): WideString; + + public + function GetParentFolder:TKTWSAPI_Folder; + end; + + /// Class representing a folder + TKTWSAPI_Folder = class(TKTWSAPI_FolderItem) + private + FFolderName, /// Name of folder + FFullPath: WideString; /// Full path to folder + + FFolderId: Integer; /// Id to folder + public + constructor Create(KTAPI:TKTWSAPI; FolderDetail: kt_folder_detail); overload; + class function Get(KTAPI: TKTWSAPI; FolderId:Integer): TKTWSAPI_Folder; + function GetParentFolderId: Integer; + function GetFolderName: WideString; + function GetFolderId: Integer; + function GetFolderByName(FolderName: WideString): TKTWSAPI_Folder; + function GetFullPath: WideString; + function GetListing(Depth: Integer=1; What: WideString = 'DF'): kt_folder_contents; + function GetDocumentByName(Title: WideString): TKTWSAPI_Document; + function GetDocumentByFileName(FileName: WideString): TKTWSAPI_Document; + function AddFolder(FolderName: WideString): TKTWSAPI_Folder; + function Delete(Reason: WideString): Boolean; + function Rename(NewName: WideString): Boolean; + function Move(TargetFolder:TKTWSAPI_Folder; Reason: WideString): Boolean; + function Copy(TargetFolder:TKTWSAPI_Folder; Reason: WideString): Boolean; + function AddDocument(FileName: WideString; Title: WideString = ''; + DocumentType: WideString = ''): TKTWSAPI_Document; + function AddDocumentBase64(FileName: WideString; Title: WideString = ''; + DocumentType: WideString = ''): TKTWSAPI_Document; + published + property FolderName: WideString read FFolderName write FFolderName; + property FullPath: WideString read FFullPath write FFullPath; + property FolderId: Integer read FFolderId write FFolderId; + end; + + /// Class representing a document + TKTWSAPI_Document = class(TKTWSAPI_FolderItem) + private + + FDocumentId: Integer; /// Id of document + FTitle, /// Title of document + FDocumentType, /// Type of document + FVersion, /// Document version + FFileName, /// Original filename + FCreatedDate, /// Date created + FCreatedBy, /// Name of user who created + FUpdatedDate, /// Date updated + FUpdatedBy, /// Name of user who updated + FWorkflow, /// Workflow + FWorkflowState, /// Workflow state + FCheckoutBy, /// Name of user who checked out + FFullPath: WideString; /// Full path to document + public + constructor Create(KTAPI: TKTWSAPI; DocumentDetail: kt_document_detail); + + class function Get(KTAPI: TKTWSAPI; DocumentId: Integer; + LoadInfo: Boolean = System.True): TKTWSAPI_Document; + function Checkin(FileName, Reason: WideString; MajorUpdate: Boolean): Boolean; + function Checkout(Reason: WideString; LocalPath: WideString = ''; + DownloadFile: Boolean = True): Boolean; + function UndoCheckout(Reason: WideString): Boolean; + function Download(Version: WideString = ''; LocalPath: WideString = ''; FileName: WideString = ''): Boolean; + function Delete(Reason: WideString): Boolean; + function ChangeOwner(UserName, Reason: WideString): Boolean; + function Copy(Folder: TKTWSAPI_Folder; Reason: WideString; + NewTitle: WideString = ''; NewFileName: WideString = ''): Boolean; + function Move(Folder: TKTWSAPI_Folder; Reason: WideString; + NewTitle: WideString = ''; NewFileName: WideString = ''): Boolean; + function ChangeDocumentType(DocumentType: WideString): Boolean; + function RenameTitle(NewTitle: WideString): Boolean; + function RenameFilename(NewFilename: WideString): Boolean; + function StartWorkflow(WorkFlow: WideString): Boolean; + function DeleteWorkflow: Boolean; + function PeformWorkflowTransition(Transition, Reason: WideString): Boolean; + function GetMetadata:kt_metadata_response; + function UpdateMetadata(Metadata: kt_metadata_fieldsets): Boolean; + function GetTransactionHistory: kt_document_transaction_history_response; + function GetVersionHistory: kt_document_version_history_response; + function GetLinks: kt_linked_document_response; + function Link(DocumentId: Integer; const LinkType: WideString): Boolean; + function Unlink(DocumentId: Integer): Boolean; + function CheckinBase64(FileName, Reason: WideString; MajorUpdate: Boolean): Boolean; + function CheckoutBase64(Reason: WideString; LocalPath: WideString = ''; + DownloadFile: Boolean = True): Boolean; + function DownloadBase64(Version: WideString = ''; LocalPath: WideString = ''): Boolean; + function GetTypes: kt_document_types_response; + function GetLinkTypes: kt_document_types_response; + + property DocumentId: Integer read FDocumentId write FDocumentId; + property Title: WideString read FTitle write FTitle; + property DocumentType: WideString read FDocumentType write FDocumentType; + property Version: WideString read FVersion write FVersion; + property FileName: WideString read FFileName write FFileName; + property CreatedDate: WideString read FCreatedBy write FCreatedBy; + property CreatedBy: WideString read FCreatedBy write FCreatedBy; + property UpdatedDate: WideString read FUpdatedDate write FUpdatedDate; + property UpdatedBy: WideString read FUpdatedBy write FUpdatedBy; + property Workflow: WideString read FWorkflow write FWorkflow; + property WorkflowState: WideString read FWorkflowState write FWorkflowState; + property CheckoutBy: WideString read FCheckoutBy write FCheckoutBy; + property FullPath: WideString read FFullPath write FFullPath; + end; + + /// Api entry point + TKTWSAPI = class + private + + FSession, /// Current session id + FDownloadPath: WideString; /// Current download path + + FSoapClient:KnowledgeTreePort; /// Object implementing the + /// KnowledgeTreePort interface + public + constructor Create(); + function GetDownloadPath: WideString; + function SetDownloadPath(DownloadPath:WideString): Boolean; + function StartAnonymousSession(Ip: WideString = ''): WideString; + function StartSession(Username, Password: WideString; Ip: WideString = ''): WideString; + function ActiveSession(Session: WideString; Ip: WideString = ''): WideString; + function Logout: Boolean; + function GetRootFolder: TKTWSAPI_Folder; + function GetFolderById(FolderId: Integer): TKTWSAPI_Folder; + function GetDocumentById(DocumentId: Integer): TKTWSAPI_Document; + published + property SoapClient: KnowledgeTreePort read FSoapClient write FSoapClient; + property Session: WideString read FSession write FSession; + end; +var + KTWebServerUrl: WideString; /// Your webserver url + KTUploadUrl: WideString; /// URL to the web-service upload.php + KTWebServiceUrl: WideString; /// URL to the web-service wsdl + +implementation + +uses + IdComponent, IdURI, IdHttp, IdMultipartFormData, IdGlobalProtocols, + uPHPSerialize, EncdDecd; +const + KTWSAPI_ERR_SESSION_IN_USE = + 'There is a session already active.'; /// Exception message when session is in use + KTWSAPI_ERR_SESSION_NOT_STARTED = + 'An active session has not been started.'; /// Exception message when session is not started + + +{ TKTWSAPI_FolderItem } + +{* + Finds the filesize of a file. + + @param FileName Path to the file + @return The size of the file as a string +*} +function TKTWSAPI_FolderItem._GetFileSize(FileName: WideString): WideString; +var + SearchRec: TSearchRec; + sgPath: string; + inRetval, I1: Integer; +begin + sgPath := ExpandFileName(FileName); + try + inRetval := FindFirst(ExpandFileName(FileName), faAnyFile, SearchRec); + if inRetval = 0 then + I1 := SearchRec.Size + else + I1 := -1; + finally + SysUtils.FindClose(SearchRec); + end; + Result := IntToStr(I1); +end; + +{* + Reads a file into a string and base64 encodes it. + + @param Base64String Base64 encoded string + @param LocalPath Path to load from + @param FileName FileName to read + @return base64 encoded string + @throws EKTWSAPI_Exception 'Could not access file to read.' +*} +function TKTWSAPI_FolderItem._LoadFileAsBase64String(FileName: WideString): WideString; +var + Stream: TFileStream; + InString: AnsiString; +begin + if not FileExists(FileName) then + raise EKTWSAPI_Exception.Create('Could not access file to read.'); + Stream := TFileStream.Create(FileName, fmOpenRead); + try + SetLength(InString, Stream.Size); + Stream.ReadBuffer(InString[1], Length(InString)); + Result := EncodeString(InString); + finally + Stream.Free; + end; +end; + +{* + Save a Base64 encoded string as a file. + + @param Base64String Base64 encoded string + @param LocalPath Path to save to + @param FileName FileName to save as + @return true if success +*} +function TKTWSAPI_FolderItem._SaveBase64StringAsFile(Base64String, LocalPath, + FileName: WideString): Boolean; +var + OutString: AnsiString; + Stream: TFileStream; + LocalFileName: String; +begin + LocalFileName := LocalPath + '/' + FileName; + OutString := DecodeString(Base64String); + Stream := TFileStream.Create(LocalFileName, fmCreate); + try + // For some reason it fails if I use WideString instead of AnsiString + Stream.WriteBuffer(Pointer(OutString)^, Length(OutString)); + Result := true; + finally + Stream.Free; + end; +end; + +{* + Upload a file to KT. + + @param FileName Path to upload file + @param Action Which action to perform with the file (A = Add, C = Checkin) + @param DocumentId Id of the document + @return The temporary filename on the server + @throws EKTWSAPI_Exception Could not access file to upload. + @throws EKTWSAPI_Exception No response from server. + @throws EKTWSAPI_Exception Could not upload file. +*} +function TKTWSAPI_FolderItem._UploadFile(FileName, Action: WideString; + DocumentId: Integer): WideString; +var + UploadName, UploadStatus, SessionId, StatusCode: WideString; + PostStream: TIdMultiPartFormDataStream; + ResponseStream: TStringStream; + Fields: TStringList; + HTTP: TIdHTTP; + UploadData: TPHPValue; + FilesArr: TPHPArray; +begin + Result := ''; + if not FileExists(FileName) then + raise EKTWSAPI_Exception.Create('Could not access file to upload.'); + // TODO: Check if file is readable + + if (DocumentId = 0) then + UploadName := 'upload_document' + else + UploadName := 'upload_'+IntToStr(DocumentId); + SessionId := FKTAPI.Session; + + HTTP := TIdHttp.Create(nil); + try + PostStream := TIdMultiPartFormDataStream.Create; + ResponseStream := TStringStream.Create(''); + Fields := TStringList.Create; + try + PostStream.AddFormField('session_id', SessionId); + PostStream.AddFormField('action', Action); + PostStream.AddFormField('document_id',IntToStr(DocumentId)); + PostStream.AddFormField(UploadName,'@' + FileName); + PostStream.AddFile('file',FileName,GetMIMETypeFromFile(FileName)); + + HTTP.Request.ContentType := PostStream.RequestContentType; + HTTP.Post(KTUploadURL, PostStream, ResponseStream); + if (ResponseStream.DataString = '') then + raise EKTWSAPI_Exception.Create('No response from server.'); + ExtractStrings(['&'], [' '], pAnsiChar(ResponseStream.DataString), Fields); + + StatusCode := Copy(Fields[0], Pos('=',Fields[0])+1, 1); + if (StatusCode <> '0') then + raise EKTWSAPI_Exception.Create('Could not upload file.'); + + + UploadStatus := Copy(Fields[1], Pos('=',Fields[1])+1, Length(Fields[1])); + UploadStatus := TIdURI.URLDecode(UploadStatus); + UploadData := TPHPSerialize.Unserialize(TIdURI.URLDecode(UploadStatus)); + Assert(Assigned(UploadData)); + Assert(Assigned(UploadData.AsArray['file'])); + try + FilesArr := UploadData.AsArray['file'].AsArray; + + if (FilesArr['size'].AsString <> _GetFileSize(FileName)) then + raise EKTWSAPI_Exception.Create('Could not upload file.'); + + Result := FilesArr['tmp_name'].AsString; + finally + UploadData.Free; + end; + finally + PostStream.Free; + ResponseStream.Free; + Fields.Free; + end; + finally + HTTP.Free; + end; +end; + +{* + Downloads a file from KT. + + @param Url Http-url to download + @param LocalPath Path to save to + @param FileName FileName to save as + @return true if success + @throws EKTWSAPI_Exception Could not create local file +*} +function TKTWSAPI_FolderItem._DownloadFile(Url, LocalPath, + FileName: WideString): Boolean; +var + Stream: TMemoryStream; + LocalFileName: WideString; + FP: File; + HTTP: TIdHTTP; +begin + LocalFileName := LocalPath + '/' + FileName; + + AssignFile(FP, LocalFileName); + {$I-} + Rewrite(FP,1); + {$I+} + if (IOResult <> 0) then + raise EKTWSAPI_Exception.Create('Could not create local file'); + CloseFile(FP); + HTTP := TIdHttp.Create(Nil); + try + Stream := TMemoryStream.Create; + try + HTTP.Get(Url, Stream); + Stream.SaveToFile(LocalFileName); + Result := true; + finally + Stream.Free; + end; + finally + HTTP.Free; + end; +end; + +{* + Returns a reference to the parent folder. + + @return Handle to parent folder +*} +function TKTWSAPI_FolderItem.GetParentFolder: TKTWSAPI_Folder; +begin + Result := FKTAPI.GetFolderById(FParentId); +end; + + + { TKTWSAPI_Folder } + +{* + Constructor + + @param KTAPI Handle to KTAPI object + @param FolderDetail Handle to kt_folder_detail +*} +constructor TKTWSAPI_Folder.Create(KTAPI: TKTWSAPI; + FolderDetail: kt_folder_detail); +begin + FKTAPI := KTAPI; + FFolderId := FolderDetail.id; + FFolderName := FolderDetail.folder_name; + FParentId := FolderDetail.parent_id; + FFullPath := FolderDetail.full_path; +end; + +{* + Returns a reference to a TKTWSAPI_Folder + + @param KTAPI Handle to KTAPI object + @param FolderId Id of folder to fetch + @return folder handle + @throws EKTWSAPI_Exception Response message +*} +class function TKTWSAPI_Folder.Get(KTAPI: TKTWSAPI; + FolderId: Integer): TKTWSAPI_Folder; +var + FolderDetail: kt_folder_detail; +begin + Assert(Assigned(KTAPI)); + Assert(KTAPI.ClassNameIs('TKTWSAPI')); + Result := nil; + + FolderDetail := KTAPI.SoapClient.get_folder_detail(KTAPI.Session, FolderId); + try + if (FolderDetail.status_code <> 0) then + raise EKTWSAPI_Exception.Create(FolderDetail.message_); + + Result := TKTWSAPI_Folder.Create(KTAPI, FolderDetail); + + finally + FolderDetail.Free; + end; +end; + +{* + Returns the parent folder id. + + @return parent folder id +*} +function TKTWSAPI_Folder.GetParentFolderId: Integer; +begin + Result := FParentId; +end; + +{* + Returns the folder name. + + @return folder name +*} +function TKTWSAPI_Folder.GetFolderName: WideString; +begin + Result := FFolderName; +end; + +{* + Returns the current folder id. + + @return current folder id +*} +function TKTWSAPI_Folder.GetFolderId: Integer; +begin + Result := FFolderId; +end; + +{* + Returns the folder based on foldername. + + @param FolderName Name of folder + @return folder handle + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Folder.GetFolderByName(FolderName: WideString): TKTWSAPI_Folder; +var + Path: WideString; + FolderDetail: kt_folder_detail; +begin + Path := FFullPath + '/' + FolderName; + if (System.Copy(Path, 0, 13) = '/Root Folder/') then + Path := System.Copy(Path, 13, Length(Path)-1); + if (System.Copy(Path, 0, 12) = 'Root Folder/') then + Path := System.Copy(Path, 12, Length(Path)-1); + + FolderDetail := FKTAPI.SoapClient.get_folder_detail_by_name(FKTAPI.Session, + Path); + + if (FolderDetail.status_code <> 0) then + raise EKTWSAPI_Exception.Create(FolderDetail.message_); + + Result := TKTWSAPI_Folder.Create(FKTAPI, FolderDetail); +end; + +{* + Returns the full folder path. + + @return Full folder path +*} +function TKTWSAPI_Folder.GetFullPath: WideString; +begin + Result := FFullPath; +end; + +{* + Returns the contents of a folder. + + @param Depth How many sub-folders to fetch + @param What to fetch (F=Folders, D=Documents, FD=Both) + @return folder contents handle + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Folder.GetListing(Depth: Integer; + What: WideString): kt_folder_contents; +begin + Result := FKTAPI.SoapClient.get_folder_contents( + FKTAPI.Session, FFolderId, Depth, What); + + if (Result.status_code <> 0) then + raise EKTWSAPI_Exception.Create(Result.message_); +end; + +{* + Returns a document based on title. + + @param Title Title of document + @return document handle + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Folder.GetDocumentByName(Title: WideString): TKTWSAPI_Document; +var + Path: WideString; + DocumentDetail: kt_document_detail; +begin + Path := FFullPath + '/' + Title; + if (System.Copy(Path, 0, 13) = '/Root Folder/') then + Path := System.Copy(Path, 13, Length(Path)-1); + if (System.Copy(Path, 0, 12) = 'Root Folder/') then + Path := System.Copy(Path, 12, Length(Path)-1); + + DocumentDetail := FKTAPI.SoapClient.get_document_detail_by_name(FKTAPI.Session, + Path, 'T'); + + if (DocumentDetail.status_code <> 0) then + raise EKTWSAPI_Exception.Create(DocumentDetail.message_); + + Result := TKTWSAPI_Document.Create(FKTAPI, DocumentDetail); +end; + +{* + Returns a document based on filename. + + @param FileName Name of file + @return document handle + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Folder.GetDocumentByFileName( + FileName: WideString): TKTWSAPI_Document; +var + Path: WideString; + DocumentDetail: kt_document_detail; +begin + Result := nil; + Path := FFullPath + '/' + FileName; + if (System.Copy(Path, 0, 13) = '/Root Folder/') then + Path := System.Copy(Path, 13, Length(Path)-1); + if (System.Copy(Path, 0, 12) = 'Root Folder/') then + Path := System.Copy(Path, 12, Length(Path)-1); + + DocumentDetail := FKTAPI.SoapClient.get_document_detail_by_name(FKTAPI.Session, + Path, 'F'); + try + if (DocumentDetail.status_code <> 0) then + raise EKTWSAPI_Exception.Create(DocumentDetail.message_); + Result := TKTWSAPI_Document.Create(FKTAPI, DocumentDetail); + finally + DocumentDetail.Free; + end; +end; + +{* + Adds a sub folder. + + @param FolderName Name of folder + @return new folder handle + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Folder.AddFolder(FolderName: WideString): TKTWSAPI_Folder; +var + FolderDetail: kt_folder_detail; +begin + Result := nil; + FolderDetail := FKTAPI.SoapClient.create_folder(FKTAPI.Session, FFolderId, FolderName); + try + if (FolderDetail.status_code <> 0) then + raise EKTWSAPI_Exception.Create(FolderDetail.message_); + + Result := TKTWSAPI_Folder.Create(FKTAPI, FolderDetail); + finally + FolderDetail.Free; + end; +end; + +{* + Deletes the current folder. + + @param Reason Reason for deletetion + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Folder.Delete(Reason: WideString): Boolean; +var + response: kt_response; +begin + // TODO: check why no transaction in folder_transactions + Result := System.False; + response := FKTAPI.SoapClient.delete_folder(FKTAPI.Session, + FFolderId, Reason); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + Result := System.True; + finally + response.Free; + end; +end; + +{* + Renames the current folder. + + @param NewName New folder name + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Folder.Rename(NewName: WideString): Boolean; +var + response: kt_response; +begin + Result := System.False; + response := FKTAPI.SoapClient.rename_folder(FKTAPI.Session, + FFolderId, NewName); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + Result := System.True; + finally + response.Free; + end; +end; + +{* + Moves a folder to another location. + + @param TargetFolder Handle to target folder + @param Reason Reason for move + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Folder.Move(TargetFolder: TKTWSAPI_Folder; + Reason: WideString): Boolean; +var + response: kt_response; +begin + Result := System.False; + Assert(Assigned(TargetFolder)); + Assert(TargetFolder.ClassNameIs('TKTWSAPI_Folder')); + + response := FKTAPI.SoapClient.move_folder(FKTAPI.Session, + FFolderId, TargetFolder.GetFolderId, Reason); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + Result := System.True; + finally + response.Free; + end; +end; + +{* + Copies a folder to another location + + @param TargetFolder Handle to target folder + @param Reason Reason for copy + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Folder.Copy(TargetFolder: TKTWSAPI_Folder; + Reason: WideString): Boolean; +var + TargetId: Integer; + response: kt_response; +begin + Result := System.False; + Assert(Assigned(TargetFolder)); + Assert(TargetFolder.ClassNameIs('TKTWSAPI_Folder')); + + TargetId := TargetFolder.GetFolderId; + response := FKTAPI.SoapClient.copy_folder(FKTAPI.Session, + FFolderId, TargetId, Reason); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + Result := System.True; + finally + response.Free; + end; +end; + +{* + Adds a document to the current folder. + + @param FileName FileName to upload + @param Title Title to give document + @param DocumentType Documenttype of document (Default is 'Default') + @return handle to new document + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Folder.AddDocument(FileName, Title, + DocumentType: WideString): TKTWSAPI_Document; +var + BaseName, TempFileName: WideString; + DocumentDetail: kt_document_detail; +begin + Result := nil; + BaseName := ExtractFileName(FileName); + if (Title = '') then + Title := BaseName; + if (DocumentType = '') then + DocumentType := 'Default'; + + TempFileName := _UploadFile(FileName, 'A'); + DocumentDetail := FKTAPI.FSoapClient.add_document(FKTAPI.Session, FFolderId, + Title, BaseName, DocumentType, TempFileName); + try + if (DocumentDetail.status_code <> 0) then + raise EKTWSAPI_Exception.Create(DocumentDetail.message_); + + Result := TKTWSAPI_Document.Create(FKTAPI, DocumentDetail); + finally + DocumentDetail.Free; + end; +end; + +{* + Adds a document to the current folder through web service. + + @param FileName FileName to upload + @param Title Title to give document + @param DocumentType Documenttype of document (Default is 'Default') + @return handle to new document + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Folder.AddDocumentBase64(FileName, Title, + DocumentType: WideString): TKTWSAPI_Document; +begin + raise EKTWSAPI_Exception.Create('Not implemented yet!'); +end; + +{ TKTWSAPI_Document } + +{* + Constructor + + @param KTAPI Handle to KTAPI object + @param DocumentDetail handle to kt_document_detail +*} +constructor TKTWSAPI_Document.Create(KTAPI: TKTWSAPI; + DocumentDetail: kt_document_detail); +begin + FKTAPI := KTAPI; + FDocumentId := DocumentDetail.document_id; + FTitle := DocumentDetail.title; + FDocumentType := DocumentDetail.document_type; + FVersion := DocumentDetail.version; + FFilename := DocumentDetail.filename; + FCreatedDate := DocumentDetail.created_date; + FCreatedBy := DocumentDetail.created_by; + FUpdatedDate := DocumentDetail.updated_date; + FUpdatedBy := DocumentDetail.updated_by; + FParentId := DocumentDetail.folder_id; + FWorkflow := DocumentDetail.workflow; + FWorkflowState := DocumentDetail.workflow_state; + FCheckoutBy := DocumentDetail.checkout_by; + FFullPath := DocumentDetail.full_path; +end; + +{* + Returns a reference to a document. + + @param KTAPI Handle to KTAPI object + @param DocumentId Id of document + @param LoadInfo Call web service to load document details + @return handle to document + @throws EKTWSAPI_Exception Response message +*} +class function TKTWSAPI_Document.Get(KTAPI: TKTWSAPI; DocumentId: Integer; + LoadInfo: Boolean): TKTWSAPI_Document; +var + DocumentDetail:kt_document_detail; +begin + Assert(Assigned(KTAPI)); + Assert(KTAPI.ClassNameIs('TKTWSAPI')); + if LoadInfo then + begin + DocumentDetail := KTAPI.SoapClient.get_document_detail(KTAPI.Session, DocumentId); + + if (DocumentDetail.status_code <> 0) then + raise EKTWSAPI_Exception.Create(DocumentDetail.message_); + + end else + begin + DocumentDetail := kt_document_detail.Create; + DocumentDetail.document_id := DocumentId; + end; + try + Result := TKTWSAPI_Document.Create(KTAPI, DocumentDetail); + finally + DocumentDetail.Free; + end; +end; + +{* + Checks in a document. + + @param FileName Name of file to checkin + @param Reason Reason for checkin + @param MajorUpdate Checkin as a major update (bumps major version number) + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.Checkin(FileName, Reason: WideString; + MajorUpdate: Boolean): Boolean; +var + BaseName, TempFileName: WideString; + response: kt_response; +begin + Result := System.False; + BaseName := ExtractFileName(FileName); + + TempFileName := _UploadFile(FileName, 'C', FDocumentId); + response := FKTAPI.SoapClient.checkin_document(FKTAPI.Session, FDocumentId, BaseName, Reason, TempFileName, MajorUpdate); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + Result := System.True; + finally + response.Free; + end; +end; + +{* + Checks out a document. + + @param Reason Reason for checkout + @param LocalPath to save downloaded file to + @param DownloadFile if false then checkout will happen without download + @return true + @throws EKTWSAPI_Exception local path does not exist + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.Checkout(Reason, LocalPath: WideString; + DownloadFile: Boolean): Boolean; +var + response: kt_response; + Url: WideString; +begin + Result := System.False; + if (LocalPath = '') then LocalPath := FKTAPI.GetDownloadPath; + + if not DirectoryExists(LocalPath) then + raise EKTWSAPI_Exception.Create('local path does not exist'); + + // TODO check if Directory is writable + + response := FKTAPI.SoapClient.checkout_document(FKTAPI.Session, FDocumentId, Reason); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + + Url := response.message_; + + if DownloadFile then + _DownloadFile(KTWebServerURL+Url, LocalPath, FFileName); + + Result := System.True; + finally + response.Free; + end; +end; + +{* + Undo a document checkout + + @param Reason Reason for undoing the checkout + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.UndoCheckout(Reason: WideString): Boolean; +var + response: kt_response; +begin + Result := System.False; + response := FKTAPI.SoapClient.undo_document_checkout(FKTAPI.Session, FDocumentId, Reason); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + + Result := System.True; + finally + response.Free; + end; +end; + +{* + Download a version of the document + + @param Version Which version of document to download + @param LocalPath Optional path to save file to + @param FileName Optional filename to save file as + @return true + @throws EKTWSAPI_Exception local path does not exist + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.Download(Version, LocalPath, FileName: WideString): Boolean; +var + response: kt_response; + Url: WideString; +begin + Result := System.False; + if (LocalPath = '') then LocalPath := FKTAPI.GetDownloadPath; + if (FileName = '') then FileName := FFileName; + + if (not DirectoryExists(LocalPath)) then + raise EKTWSAPI_Exception.Create('local path does not exist'); + + // TODO: Check if local path is writable + + response := FKTAPI.SoapClient.download_document(FKTAPI.Session, FDocumentId); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + Url := response.message_; + Result := _DownloadFile(KTWebServerURL+Url, LocalPath, FileName); + finally + response.Free; + end; +end; + + +{* + Download a version of the document through webservice + + @param Version Which version of document to download + @param LocalPath Path to save file to + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.DownloadBase64(Version, + LocalPath: WideString): Boolean; +var + response: kt_response; +begin + Result := System.False; + if (LocalPath = '') then LocalPath := FKTAPI.GetDownloadPath; + if (FileName = '') then FileName := FFileName; + + if (not DirectoryExists(LocalPath)) then + raise EKTWSAPI_Exception.Create('local path does not exist'); + + // TODO: Check if local path is writable + + response := FKTAPI.SoapClient.download_base64_document(FKTAPI.Session, FDocumentId); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + Result := _SaveBase64StringAsFile(response.message_, LocalPath, FileName); + finally + response.Free; + end; +end; + +{* + Deletes the current document. + + @param Reason Reason for delete + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.Delete(Reason: WideString): Boolean; +var + response: kt_response; +begin + Result := System.False; + response := FKTAPI.SoapClient.delete_document(FKTAPI.Session, FDocumentId, Reason); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + + Result := System.True; + finally + response.Free; + end; +end; + +{* + Changes the owner of the document. + + @param UserName Username of new owner + @param Reason Reason for the owner change + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.ChangeOwner(UserName, Reason: WideString): Boolean; +var + response: kt_response; +begin + Result := System.False; + response := FKTAPI.SoapClient.change_document_owner(FKTAPI.Session, FDocumentId, UserName, Reason); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + + Result := System.True; + finally + response.Free; + end; +end; + +{* + Copies the current document to the specified folder. + + @param Folder Handle to target folder + @param Reason Reason for copy + @param NewTitle New title of the file + @param NewFileName New filename of the file + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.Copy(Folder: TKTWSAPI_Folder; Reason, NewTitle, + NewFileName: WideString): Boolean; +var + response: kt_response; + FolderId: Integer; +begin + Result := System.False; + Assert(Assigned(Folder)); + Assert(Folder.ClassNameIs('TKTWSAPI_Folder')); + FolderId := Folder.GetFolderId; + + response := FKTAPI.SoapClient.copy_document(FKTAPI.Session, FDocumentId, FolderId, Reason, NewTitle, NewFileName); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + + Result := System.True; + finally + response.Free; + end; +end; + +{* + Moves the current document to the specified folder. + + @param Folder Handle to target folder + @param Reason Reason for move + @param NewTitle New title of the file + @param NewFileName New filename of the file + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.Move(Folder: TKTWSAPI_Folder; Reason, NewTitle, + NewFileName: WideString): Boolean; +var + response: kt_response; + FolderId: Integer; +begin + Result := System.False; + Assert(Assigned(Folder)); + Assert(Folder.ClassNameIs('TKTWSAPI_Folder')); + FolderId := Folder.GetFolderId; + + response := FKTAPI.SoapClient.move_document(FKTAPI.Session, FDocumentId, FolderId, Reason, NewTitle, NewFileName); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + Result := System.True; + finally + response.Free; + end; +end; + +{* + Changes the document type. + + @param DocumentType DocumentType to change to + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.ChangeDocumentType(DocumentType: WideString): Boolean; +var + response: kt_response; +begin + Result := System.False; + response := FKTAPI.SoapClient.change_document_type(FKTAPI.Session, FDocumentId, DocumentType); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + + Result := System.True; + finally + response.Free; + end; +end; + +{* + Renames the title of the current document. + + @param NewTitle New title of the document + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.RenameTitle(NewTitle: WideString): Boolean; +var + response: kt_response; +begin + Result := System.False; + response := FKTAPI.SoapClient.rename_document_title(FKTAPI.Session, FDocumentId, NewTitle); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + + Result := System.True; + finally + response.Free; + end; +end; + +{* + Renames the filename of the current document. + + @param NewFilename New filename of the document + @return true +*} +function TKTWSAPI_Document.RenameFilename(NewFilename: WideString): Boolean; +var + response: kt_response; +begin + Result := System.False; + response := FKTAPI.SoapClient.rename_document_filename(FKTAPI.Session, FDocumentId, NewFilename); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + + Result := System.True; + finally + response.Free; + end; +end; + +{* + Starts a workflow on the current document. + + @param WorkFlow Workflow + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.StartWorkflow(WorkFlow: WideString): Boolean; +var + response: kt_response; +begin + Result := System.False; + response := FKTAPI.SoapClient.start_document_workflow(FKTAPI.Session, FDocumentId, WorkFlow); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + + Result := System.True; + finally + response.Free; + end; +end; + +{* + Removes the workflow process from the current document. + + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.DeleteWorkflow: Boolean; +var + response: kt_response; +begin + Result := System.False; + response := FKTAPI.SoapClient.delete_document_workflow(FKTAPI.Session, FDocumentId); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + + Result := System.True; + finally + response.Free; + end; +end; + +{* + Performs a transition on the current document. + + @param Transition Transition + @param Reason Reason for transition + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.PeformWorkflowTransition(Transition, + Reason: WideString): Boolean; +var + response: kt_response; +begin + Result := System.False; + response := FKTAPI.SoapClient.perform_document_workflow_transition(FKTAPI.Session, FDocumentId, Transition, Reason); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + + Result := System.True; + finally + response.Free; + end; +end; + +{* + Returns metadata on the document. + + @return handle to metadata + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.GetMetadata: kt_metadata_response; +begin + Result := FKTAPI.SoapClient.get_document_metadata(FKTAPI.Session, FDocumentId); + + if (Result.status_code <> 0) then + raise EKTWSAPI_Exception.Create(Result.message_); +end; + +{* + Updates the metadata on the current document. + + @param Metadata Handle to metadata + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.UpdateMetadata( + Metadata: kt_metadata_fieldsets): Boolean; +var + response: kt_response; +begin + Result := System.False; + response := FKTAPI.SoapClient.update_document_metadata(FKTAPI.Session, FDocumentId, MetaData); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + + Result := System.True; + finally + response.Free; + end; +end; + +{* + Returns the transaction history on the current document. + + @return handle to transaction history + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.GetTransactionHistory: kt_document_transaction_history_response; +begin + Result := FKTAPI.SoapClient.get_document_transaction_history(FKTAPI.Session, FDocumentId); + if (Result.status_code <> 0) then + raise EKTWSAPI_Exception.Create(Result.message_); +end; + +{* + Returns the version history on the current document. + + @return handle to document version history + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.GetVersionHistory: kt_document_version_history_response; +begin + Result := FKTAPI.SoapClient.get_document_version_history(FKTAPI.Session, FDocumentId); + if (Result.status_code <> 0) then + raise EKTWSAPI_Exception.Create(Result.message_); +end; + +{* + Returns the links of the current document + + @return handle to document version history + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.GetLinks: kt_linked_document_response; +begin + Result := FKTAPI.SoapClient.get_document_links(FKTAPI.Session, FDocumentId); + if (Result.status_code <> 0) then + raise EKTWSAPI_Exception.Create(Result.message_); +end; + +{* + Links the current document to a DocumentId + + @param DocumentId DocumentId to link to + @param LinkType Type of link + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.Link(DocumentId: Integer; + const LinkType: WideString): Boolean; +var + response: kt_response; +begin + Result := System.False; + response := FKTAPI.SoapClient.link_documents(FKTAPI.Session, FDocumentId, + DocumentId, LinkType); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + Result := System.True; + finally + response.Free; + end; +end; + +{* + Unlinks the current document from a DocumentId + + @param DocumentId DocumentId to unlink to + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.Unlink(DocumentId: Integer): Boolean; +var + response: kt_response; +begin + Result := System.False; + response := FKTAPI.SoapClient.unlink_documents(FKTAPI.Session, FDocumentId, + DocumentId); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + Result := System.True; + finally + response.Free; + end; +end; + +{* + Checks out a document and downloads document through webservice + + @param Reason Reason for checkout + @param LocalPath to save downloaded file to + @return true + @throws EKTWSAPI_Exception local path does not exist + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.CheckoutBase64(Reason, + LocalPath: WideString; DownloadFile: Boolean): Boolean; +var + response: kt_response; +begin + Result := System.False; + if (LocalPath = '') then LocalPath := FKTAPI.GetDownloadPath; + + if not DirectoryExists(LocalPath) then + raise EKTWSAPI_Exception.Create('local path does not exist'); + + // TODO check if Directory is writable + + response := FKTAPI.SoapClient.checkout_base64_document(FKTAPI.Session, FDocumentId, Reason, DownloadFile); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + Result := True; + if DownloadFile then + Result := _SaveBase64StringAsFile(response.message_, LocalPath, FFileName); + finally + response.Free; + end; +end; + +{* + Gets list of document types + + @return handle to document types response + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.GetTypes: kt_document_types_response; +begin + Result := FKTAPI.SoapClient.get_document_types(FKTAPI.Session); + if (Result.status_code <> 0) then + raise EKTWSAPI_Exception.Create(Result.message_); +end; + +{* + Get list of document link types + @return handle to document types response + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.GetLinkTypes: kt_document_types_response; +begin + Result := FKTAPI.SoapClient.get_document_link_types(FKTAPI.Session); + if (Result.status_code <> 0) then + raise EKTWSAPI_Exception.Create(Result.message_); +end; + +{* + Checks in a document and uploads through webservice + + @param FileName Name of file to checkin + @param Reason Reason for checkin + @param MajorUpdate Checkin as a major update (bumps major version number) + @return true + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI_Document.CheckinBase64(FileName, Reason: WideString; + MajorUpdate: Boolean): Boolean; +var + Base64String, BaseName: WideString; + response: kt_response; +begin + Result := System.False; + Base64String := _LoadFileAsBase64String(FileName); + BaseName := ExtractFileName(FileName); + + response := FKTAPI.SoapClient.checkin_base64_document(FKTAPI.Session, + FDocumentId, BaseName, Reason, Base64String, MajorUpdate); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + Result := System.True; + finally + response.Free; + end; +end; + +{ TKTWSAPI } + +{* + Constructor +*} +constructor Tktwsapi.Create(); +begin + FSoapClient := GetKnowledgeTreePort(False, KTWebServiceUrl); + FDownloadPath := ''; +end; + +{* + This returns the default location where documents are downloaded in download() and checkout(). + + @return string +*} +function TKTWSAPI.GetDownloadPath: WideString; +begin + Result := FDownloadPath; +end; + +{* + Allows the default location for downloaded documents to be changed. + + @param DownloadPath Path to writable folder + @return true +*} +function TKTWSAPI.SetDownloadPath(DownloadPath: WideString): Boolean; +begin + if (not DirectoryExists(DownloadPath)) then + raise EKTWSAPI_Exception.Create('local path is not writable'); + // TODO : Check if folder is writable + + FDownloadPath := DownloadPath; + Result := System.True; +end; + +{* + Starts an anonymous session. + + @param Ip Users Ip-adress + @return Active session id +*} +function TKTWSAPI.StartAnonymousSession(Ip: WideString): WideString; +begin + Result := StartSession('anonymous', '', Ip); +end; + +{* + Starts a user session. + + @param Username Users username + @param Password Users password + @param Ip Users Ip-adress + @return Active session id + @throws EKTWSAPI_Exception KTWSAPI_ERR_SESSION_IN_USE + @throws EKTWSAPI_Exception Response message +*} +function TKTWSAPI.StartSession(Username, Password, Ip: WideString): WideString; +var + response: kt_response; +begin + if (FSession <> '') then + raise EKTWSAPI_Exception.Create(KTWSAPI_ERR_SESSION_IN_USE); + response := FSoapClient.login(Username, Password, Ip); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + FSession := response.message_; + Result := FSession; + finally + response.Free; + end; +end; + +{* + Sets an active session. + + @param Session Session id to activate + @param Ip Users Ip-adress + @return Active session id + @throws EKTWSAPI_Exception KTWSAPI_ERR_SESSION_IN_USE +*} +function TKTWSAPI.ActiveSession(Session, Ip: WideString): WideString; +begin + if (FSession <> '') then + raise EKTWSAPI_Exception.Create(KTWSAPI_ERR_SESSION_IN_USE); + FSession := Session; + Result := FSession; +end; + +{* + Closes an active session. + + @return true +*} +function TKTWSAPI.Logout: Boolean; +var + response: kt_response; +begin + Result := System.False; + + if (FSession = '') then + raise EKTWSAPI_Exception.Create(KTWSAPI_ERR_SESSION_NOT_STARTED); + response := FSoapClient.logout(FSession); + try + if (response.status_code <> 0) then + raise EKTWSAPI_Exception.Create(response.message_); + FSession := ''; + Result := System.True; + finally + response.Free; + end; +end; + +{* + Returns a reference to the root folder. + + @return handle to folder +*} +function TKTWSAPI.GetRootFolder: TKTWSAPI_Folder; +begin + Result := GetFolderById(1); +end; + +{* + Returns a reference to a folder based on id. + + @param FolderId Id of folder + @return handle to folder +*} +function TKTWSAPI.GetFolderById(FolderId: Integer): TKTWSAPI_Folder; +begin + if FSession = '' then + raise EKTWSAPI_Exception.Create('A session is not active'); + Result := TKTWSAPI_Folder.Get(Self, FolderId); +end; + +{* + Returns a reference to a document based on id. + + @param DocumentId Id of document + @return handle to document +*} +function TKTWSAPI.GetDocumentById(DocumentId: Integer): TKTWSAPI_Document; +begin + if FSession = '' then + raise EKTWSAPI_Exception.Create('A session is not active'); + Result := TKTWSAPI_Document.Get(Self, DocumentId) +end; + +end. diff --git a/ktwsapi/delphi/uwebservice.pas b/ktwsapi/delphi/uwebservice.pas new file mode 100644 index 0000000..43b8035 --- /dev/null +++ b/ktwsapi/delphi/uwebservice.pas @@ -0,0 +1,701 @@ +{ + Copyright (c) 2007, The Jam Warehouse Software (Pty) Ltd. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + i) Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + ii) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + iii) Neither the name of the The Jam Warehouse Software (Pty) Ltd nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES ( INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ( INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +} + +{* + Unit auto-generated by delphi's wsdl imported + + @Author Bjarte Kalstveit Vebjørnsen + @Version 1.0 BKV 24.09.2007 Initial revision +*} + +// ************************************************************************ // +// The types declared in this file were generated from data read from the +// WSDL File described below: +// WSDL : http://ktdms.trunk/ktwebservice/webservice.php?wsdl +// Codegen : [wfDebug,wfGenerateWarnings,wfUseSerializerClassForAttrs] +// Version : 1.0 +// (23.09.2007 21:20:12 - 1.33.2.6) +// ************************************************************************ // + +unit uwebservice; + +interface + +uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns; + +type + + // ************************************************************************ // + // The following types, referred to in the WSDL document are not being represented + // in this file. They are either aliases[@] of other types represented or were referred + // to but never[!] declared in the document. The types from the latter category + // typically map to predefined/known XML or Borland types; however, they could also + // indicate incorrect WSDL documents that failed to declare or import a schema type. + // ************************************************************************ // + // !:int - "http://www.w3.org/2001/XMLSchema" + // !:string - "http://www.w3.org/2001/XMLSchema" + // !:boolean - "http://www.w3.org/2001/XMLSchema" + + kt_response = class; { "urn:KnowledgeTree" } + kt_folder_detail = class; { "urn:KnowledgeTree" } + kt_folder_item = class; { "urn:KnowledgeTree" } + kt_folder_contents = class; { "urn:KnowledgeTree" } + kt_document_detail = class; { "urn:KnowledgeTree" } + kt_metadata_selection_item = class; { "urn:KnowledgeTree" } + kt_metadata_field = class; { "urn:KnowledgeTree" } + kt_metadata_fieldset = class; { "urn:KnowledgeTree" } + kt_metadata_response = class; { "urn:KnowledgeTree" } + kt_document_transitions_response = class; { "urn:KnowledgeTree" } + kt_document_transaction_history_item = class; { "urn:KnowledgeTree" } + kt_linked_document = class; { "urn:KnowledgeTree" } + kt_linked_document_response = class; { "urn:KnowledgeTree" } + kt_document_transaction_history_response = class; { "urn:KnowledgeTree" } + kt_document_version_history_item = class; { "urn:KnowledgeTree" } + kt_document_version_history_response = class; { "urn:KnowledgeTree" } + kt_document_types_response = class; { "urn:KnowledgeTree" } + + + + // ************************************************************************ // + // Namespace : urn:KnowledgeTree + // ************************************************************************ // + kt_response = class(TRemotable) + private + Fstatus_code: Integer; + Fmessage_: WideString; + published + property status_code: Integer read Fstatus_code write Fstatus_code; + property message_: WideString read Fmessage_ write Fmessage_; + end; + + + + // ************************************************************************ // + // Namespace : urn:KnowledgeTree + // ************************************************************************ // + kt_folder_detail = class(TRemotable) + private + Fstatus_code: Integer; + Fmessage_: WideString; + Fid: Integer; + Ffolder_name: WideString; + Fparent_id: Integer; + Ffull_path: WideString; + published + property status_code: Integer read Fstatus_code write Fstatus_code; + property message_: WideString read Fmessage_ write Fmessage_; + property id: Integer read Fid write Fid; + property folder_name: WideString read Ffolder_name write Ffolder_name; + property parent_id: Integer read Fparent_id write Fparent_id; + property full_path: WideString read Ffull_path write Ffull_path; + end; + + kt_folder_items = array of kt_folder_item; { "urn:KnowledgeTree" } + + + // ************************************************************************ // + // Namespace : urn:KnowledgeTree + // ************************************************************************ // + kt_folder_item = class(TRemotable) + private + Fid: Integer; + Fitem_type: WideString; + Ftitle: WideString; + Fcreator: WideString; + Fchecked_out_by: WideString; + Fmodified_by: WideString; + Ffilename: WideString; + Fsize: WideString; + Fmajor_version: WideString; + Fminor_version: WideString; + Fstorage_path: WideString; + Fmime_type: WideString; + Fmime_icon_path: WideString; + Fmime_display: WideString; + Fworkflow: WideString; + Fworkflow_state: WideString; + Fitems: kt_folder_items; + public + destructor Destroy; override; + published + property id: Integer read Fid write Fid; + property item_type: WideString read Fitem_type write Fitem_type; + property title: WideString read Ftitle write Ftitle; + property creator: WideString read Fcreator write Fcreator; + property checked_out_by: WideString read Fchecked_out_by write Fchecked_out_by; + property modified_by: WideString read Fmodified_by write Fmodified_by; + property filename: WideString read Ffilename write Ffilename; + property size: WideString read Fsize write Fsize; + property major_version: WideString read Fmajor_version write Fmajor_version; + property minor_version: WideString read Fminor_version write Fminor_version; + property storage_path: WideString read Fstorage_path write Fstorage_path; + property mime_type: WideString read Fmime_type write Fmime_type; + property mime_icon_path: WideString read Fmime_icon_path write Fmime_icon_path; + property mime_display: WideString read Fmime_display write Fmime_display; + property workflow: WideString read Fworkflow write Fworkflow; + property workflow_state: WideString read Fworkflow_state write Fworkflow_state; + property items: kt_folder_items read Fitems write Fitems; + end; + + + + // ************************************************************************ // + // Namespace : urn:KnowledgeTree + // ************************************************************************ // + kt_folder_contents = class(TRemotable) + private + Fstatus_code: Integer; + Fmessage_: WideString; + Ffolder_id: Integer; + Ffolder_name: WideString; + Ffull_path: WideString; + Fitems: kt_folder_items; + public + destructor Destroy; override; + published + property status_code: Integer read Fstatus_code write Fstatus_code; + property message_: WideString read Fmessage_ write Fmessage_; + property folder_id: Integer read Ffolder_id write Ffolder_id; + property folder_name: WideString read Ffolder_name write Ffolder_name; + property full_path: WideString read Ffull_path write Ffull_path; + property items: kt_folder_items read Fitems write Fitems; + end; + + + + // ************************************************************************ // + // Namespace : urn:KnowledgeTree + // ************************************************************************ // + kt_document_detail = class(TRemotable) + private + Fstatus_code: Integer; + Fmessage_: WideString; + Ftitle: WideString; + Fdocument_type: WideString; + Fversion: WideString; + Ffilename: WideString; + Fcreated_date: WideString; + Fcreated_by: WideString; + Fupdated_date: WideString; + Fupdated_by: WideString; + Fdocument_id: Integer; + Ffolder_id: Integer; + Fworkflow: WideString; + Fworkflow_state: WideString; + Fcheckout_by: WideString; + Ffull_path: WideString; + published + property status_code: Integer read Fstatus_code write Fstatus_code; + property message_: WideString read Fmessage_ write Fmessage_; + property title: WideString read Ftitle write Ftitle; + property document_type: WideString read Fdocument_type write Fdocument_type; + property version: WideString read Fversion write Fversion; + property filename: WideString read Ffilename write Ffilename; + property created_date: WideString read Fcreated_date write Fcreated_date; + property created_by: WideString read Fcreated_by write Fcreated_by; + property updated_date: WideString read Fupdated_date write Fupdated_date; + property updated_by: WideString read Fupdated_by write Fupdated_by; + property document_id: Integer read Fdocument_id write Fdocument_id; + property folder_id: Integer read Ffolder_id write Ffolder_id; + property workflow: WideString read Fworkflow write Fworkflow; + property workflow_state: WideString read Fworkflow_state write Fworkflow_state; + property checkout_by: WideString read Fcheckout_by write Fcheckout_by; + property full_path: WideString read Ffull_path write Ffull_path; + end; + + + + // ************************************************************************ // + // Namespace : urn:KnowledgeTree + // ************************************************************************ // + kt_metadata_selection_item = class(TRemotable) + private + Fid: Integer; + Fname_: WideString; + Fvalue: WideString; + Fparent_id: Integer; + published + property id: Integer read Fid write Fid; + property name_: WideString read Fname_ write Fname_; + property value: WideString read Fvalue write Fvalue; + property parent_id: Integer read Fparent_id write Fparent_id; + end; + + kt_metadata_selection = array of kt_metadata_selection_item; { "urn:KnowledgeTree" } + + + // ************************************************************************ // + // Namespace : urn:KnowledgeTree + // ************************************************************************ // + kt_metadata_field = class(TRemotable) + private + Fname_: WideString; + Frequired: Boolean; + Fvalue: WideString; + Fdescription: WideString; + Fcontrol_type: WideString; + Fselection: kt_metadata_selection; + public + destructor Destroy; override; + published + property name_: WideString read Fname_ write Fname_; + property required: Boolean read Frequired write Frequired; + property value: WideString read Fvalue write Fvalue; + property description: WideString read Fdescription write Fdescription; + property control_type: WideString read Fcontrol_type write Fcontrol_type; + property selection: kt_metadata_selection read Fselection write Fselection; + end; + + kt_metadata_fields = array of kt_metadata_field; { "urn:KnowledgeTree" } + + + // ************************************************************************ // + // Namespace : urn:KnowledgeTree + // ************************************************************************ // + kt_metadata_fieldset = class(TRemotable) + private + Ffieldset: WideString; + Fdescription: WideString; + Ffields: kt_metadata_fields; + public + destructor Destroy; override; + published + property fieldset: WideString read Ffieldset write Ffieldset; + property description: WideString read Fdescription write Fdescription; + property fields: kt_metadata_fields read Ffields write Ffields; + end; + + kt_metadata_fieldsets = array of kt_metadata_fieldset; { "urn:KnowledgeTree" } + + + // ************************************************************************ // + // Namespace : urn:KnowledgeTree + // ************************************************************************ // + kt_metadata_response = class(TRemotable) + private + Fstatus_code: Integer; + Fmessage_: WideString; + Fmetadata: kt_metadata_fieldsets; + public + destructor Destroy; override; + published + property status_code: Integer read Fstatus_code write Fstatus_code; + property message_: WideString read Fmessage_ write Fmessage_; + property metadata: kt_metadata_fieldsets read Fmetadata write Fmetadata; + end; + + kt_document_transitions = array of WideString; { "urn:KnowledgeTree" } + + + // ************************************************************************ // + // Namespace : urn:KnowledgeTree + // ************************************************************************ // + kt_document_transitions_response = class(TRemotable) + private + Fstatus_code: Integer; + Fmessage_: WideString; + Fmetadata: kt_document_transitions; + published + property status_code: Integer read Fstatus_code write Fstatus_code; + property message_: WideString read Fmessage_ write Fmessage_; + property metadata: kt_document_transitions read Fmetadata write Fmetadata; + end; + + + + // ************************************************************************ // + // Namespace : urn:KnowledgeTree + // ************************************************************************ // + kt_document_transaction_history_item = class(TRemotable) + private + Ftransaction_name: WideString; + Fusername: WideString; + Fversion: WideString; + Fcomment: WideString; + Fdatetime: WideString; + published + property transaction_name: WideString read Ftransaction_name write Ftransaction_name; + property username: WideString read Fusername write Fusername; + property version: WideString read Fversion write Fversion; + property comment: WideString read Fcomment write Fcomment; + property datetime: WideString read Fdatetime write Fdatetime; + end; + + + + // ************************************************************************ // + // Namespace : urn:KnowledgeTree + // ************************************************************************ // + kt_linked_document = class(TRemotable) + private + Fdocument_id: Integer; + Ftitle: WideString; + Fsize: Integer; + Fworkflow: WideString; + Fworkflow_state: WideString; + Flink_type: WideString; + published + property document_id: Integer read Fdocument_id write Fdocument_id; + property title: WideString read Ftitle write Ftitle; + property size: Integer read Fsize write Fsize; + property workflow: WideString read Fworkflow write Fworkflow; + property workflow_state: WideString read Fworkflow_state write Fworkflow_state; + property link_type: WideString read Flink_type write Flink_type; + end; + + kt_linked_documents = array of kt_linked_document; { "urn:KnowledgeTree" } + + + // ************************************************************************ // + // Namespace : urn:KnowledgeTree + // ************************************************************************ // + kt_linked_document_response = class(TRemotable) + private + Fstatus_code: Integer; + Fmessage_: WideString; + Fparent_document_id: WideString; + Flinks: kt_linked_documents; + public + destructor Destroy; override; + published + property status_code: Integer read Fstatus_code write Fstatus_code; + property message_: WideString read Fmessage_ write Fmessage_; + property parent_document_id: WideString read Fparent_document_id write Fparent_document_id; + property links: kt_linked_documents read Flinks write Flinks; + end; + + kt_document_transaction_history = array of kt_document_transaction_history_item; { "urn:KnowledgeTree" } + + + // ************************************************************************ // + // Namespace : urn:KnowledgeTree + // ************************************************************************ // + kt_document_transaction_history_response = class(TRemotable) + private + Fstatus_code: Integer; + Fmessage_: WideString; + Fhistory: kt_document_transaction_history; + public + destructor Destroy; override; + published + property status_code: Integer read Fstatus_code write Fstatus_code; + property message_: WideString read Fmessage_ write Fmessage_; + property history: kt_document_transaction_history read Fhistory write Fhistory; + end; + + + + // ************************************************************************ // + // Namespace : urn:KnowledgeTree + // ************************************************************************ // + kt_document_version_history_item = class(TRemotable) + private + Fuser: Integer; + Fmetadata_version: WideString; + Fcontent_version: WideString; + published + property user: Integer read Fuser write Fuser; + property metadata_version: WideString read Fmetadata_version write Fmetadata_version; + property content_version: WideString read Fcontent_version write Fcontent_version; + end; + + kt_document_version_history = array of kt_document_version_history_item; { "urn:KnowledgeTree" } + + + // ************************************************************************ // + // Namespace : urn:KnowledgeTree + // ************************************************************************ // + kt_document_version_history_response = class(TRemotable) + private + Fstatus_code: Integer; + Fmessage_: WideString; + Fhistory: kt_document_version_history; + public + destructor Destroy; override; + published + property status_code: Integer read Fstatus_code write Fstatus_code; + property message_: WideString read Fmessage_ write Fmessage_; + property history: kt_document_version_history read Fhistory write Fhistory; + end; + + kt_document_types_array = array of WideString; { "urn:KnowledgeTree" } + + + // ************************************************************************ // + // Namespace : urn:KnowledgeTree + // ************************************************************************ // + kt_document_types_response = class(TRemotable) + private + Fstatus_code: Integer; + Fmessage_: WideString; + Fdocument_types: kt_document_types_array; + published + property status_code: Integer read Fstatus_code write Fstatus_code; + property message_: WideString read Fmessage_ write Fmessage_; + property document_types: kt_document_types_array read Fdocument_types write Fdocument_types; + end; + + + // ************************************************************************ // + // Namespace : http://schemas.xmlsoap.org/soap/envelope/ + // soapAction: http://schemas.xmlsoap.org/soap/envelope/#KTWebService#%operationName% + // transport : http://schemas.xmlsoap.org/soap/http + // style : rpc + // binding : KnowledgeTreeBinding + // service : KnowledgeTreeService + // port : KnowledgeTreePort + // URL : http://ktdms.trunk/ktwebservice/webservice.php + // ************************************************************************ // + KnowledgeTreePort = interface(IInvokable) + ['{FA35CA60-1DC3-B3C7-6C65-BE4E3A6A8A22}'] + function login(const username: WideString; const password: WideString; const ip: WideString): kt_response; stdcall; + function anonymous_login(const ip: WideString): kt_response; stdcall; + function logout(const session_id: WideString): kt_response; stdcall; + function get_folder_detail(const session_id: WideString; const folder_id: Integer): kt_folder_detail; stdcall; + function get_folder_detail_by_name(const session_id: WideString; const folder_name: WideString): kt_folder_detail; stdcall; + function get_folder_contents(const session_id: WideString; const folder_id: Integer; const depth: Integer; const what: WideString): kt_folder_contents; stdcall; + function create_folder(const session_id: WideString; const folder_id: Integer; const folder_name: WideString): kt_folder_detail; stdcall; + function delete_folder(const session_id: WideString; const folder_id: Integer; const reason: WideString): kt_response; stdcall; + function rename_folder(const session_id: WideString; const folder_id: Integer; const newname: WideString): kt_response; stdcall; + function get_document_links(const session_id: WideString; const document_id: Integer): kt_linked_document_response; stdcall; + function link_documents(const session_id: WideString; const parent_document_id: Integer; const child_document_id: Integer; const type_: WideString): kt_response; stdcall; + function unlink_documents(const session_id: WideString; const parent_document_id: Integer; const child_document_id: Integer): kt_response; stdcall; + function copy_folder(const session_id: WideString; const source_id: Integer; const target_id: Integer; const reason: WideString): kt_response; stdcall; + function move_folder(const session_id: WideString; const source_id: Integer; const target_id: Integer; const reason: WideString): kt_response; stdcall; + function get_document_detail(const session_id: WideString; const document_id: Integer): kt_document_detail; stdcall; + function checkin_document(const session_id: WideString; const document_id: Integer; const filename: WideString; const reason: WideString; const tempfilename: WideString; const major_update: Boolean): kt_response; stdcall; + function checkin_small_document(const session_id: WideString; const document_id: Integer; const filename: WideString; const reason: WideString; const base64: WideString; const major_update: Boolean): kt_response; stdcall; + function checkin_base64_document(const session_id: WideString; const document_id: Integer; const filename: WideString; const reason: WideString; const base64: WideString; const major_update: Boolean): kt_response; stdcall; + function add_document(const session_id: WideString; const folder_id: Integer; const title: WideString; const filename: WideString; const documentype: WideString; const tempfilename: WideString): kt_document_detail; stdcall; + function add_small_document(const session_id: WideString; const folder_id: Integer; const title: WideString; const filename: WideString; const documentype: WideString; const base64: WideString): kt_document_detail; stdcall; + function add_base64_document(const session_id: WideString; const folder_id: Integer; const title: WideString; const filename: WideString; const documentype: WideString; const base64: WideString): kt_document_detail; stdcall; + function get_document_detail_by_name(const session_id: WideString; const document_name: WideString; const what: WideString): kt_document_detail; stdcall; + function checkout_document(const session_id: WideString; const document_id: Integer; const reason: WideString): kt_response; stdcall; + function checkout_small_document(const session_id: WideString; const document_id: Integer; const reason: WideString; const download: Boolean): kt_response; stdcall; + function checkout_base64_document(const session_id: WideString; const document_id: Integer; const reason: WideString; const download: Boolean): kt_response; stdcall; + function undo_document_checkout(const session_id: WideString; const document_id: Integer; const reason: WideString): kt_response; stdcall; + function download_document(const session_id: WideString; const document_id: Integer): kt_response; stdcall; + function download_small_document(const session_id: WideString; const document_id: Integer): kt_response; stdcall; + function download_base64_document(const session_id: WideString; const document_id: Integer): kt_response; stdcall; + function delete_document(const session_id: WideString; const document_id: Integer; const reason: WideString): kt_response; stdcall; + function change_document_owner(const session_id: WideString; const document_id: Integer; const username: WideString; const reason: WideString): kt_response; stdcall; + function copy_document(const session_id: WideString; const document_id: Integer; const folder_id: Integer; const reason: WideString; const newtitle: WideString; const newfilename: WideString): kt_response; stdcall; + function move_document(const session_id: WideString; const document_id: Integer; const folder_id: Integer; const reason: WideString; const newtitle: WideString; const newfilename: WideString): kt_response; stdcall; + function rename_document_title(const session_id: WideString; const document_id: Integer; const newtitle: WideString): kt_response; stdcall; + function rename_document_filename(const session_id: WideString; const document_id: Integer; const newfilename: WideString): kt_response; stdcall; + function change_document_type(const session_id: WideString; const document_id: Integer; const documenttype: WideString): kt_response; stdcall; + function start_document_workflow(const session_id: WideString; const document_id: Integer; const workflow: WideString): kt_response; stdcall; + function delete_document_workflow(const session_id: WideString; const document_id: Integer): kt_response; stdcall; + function perform_document_workflow_transition(const session_id: WideString; const document_id: Integer; const transition: WideString; const reason: WideString): kt_response; stdcall; + function get_document_metadata(const session_id: WideString; const document_id: Integer): kt_metadata_response; stdcall; + function get_document_type_metadata(const session_id: WideString; const document_type: WideString): kt_metadata_response; stdcall; + function update_document_metadata(const session_id: WideString; const document_id: Integer; const metadata: kt_metadata_fieldsets): kt_response; stdcall; + function get_document_workflow_transitions(const session_id: WideString; const document_id: Integer): kt_document_transitions_response; stdcall; + function get_document_workflow_state(const session_id: WideString; const document_id: Integer): kt_response; stdcall; + function get_document_transaction_history(const session_id: WideString; const document_id: Integer): kt_document_transaction_history_response; stdcall; + function get_document_version_history(const session_id: WideString; const document_id: Integer): kt_document_version_history_response; stdcall; + function get_document_types(const session_id: WideString): kt_document_types_response; stdcall; + function get_document_link_types(const session_id: WideString): kt_document_types_response; stdcall; + end; + +function GetKnowledgeTreePort(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil): KnowledgeTreePort; + + +implementation + +function GetKnowledgeTreePort(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): KnowledgeTreePort; +const + defWSDL = 'http://ktdms.trunk/ktwebservice/webservice.php?wsdl'; + defURL = 'http://ktdms.trunk/ktwebservice/webservice.php'; + defSvc = 'KnowledgeTreeService'; + defPrt = 'KnowledgeTreePort'; +var + RIO: THTTPRIO; +begin + Result := nil; + if (Addr = '') then + begin + if UseWSDL then + Addr := defWSDL + else + Addr := defURL; + end; + if HTTPRIO = nil then + RIO := THTTPRIO.Create(nil) + else + RIO := HTTPRIO; + try + Result := (RIO as KnowledgeTreePort); + if UseWSDL then + begin + RIO.WSDLLocation := Addr; + RIO.Service := defSvc; + RIO.Port := defPrt; + end else + RIO.URL := Addr; + finally + if (Result = nil) and (HTTPRIO = nil) then + RIO.Free; + end; +end; + + +destructor kt_folder_item.Destroy; +var + I: Integer; +begin + for I := 0 to Length(Fitems)-1 do + if Assigned(Fitems[I]) then + Fitems[I].Free; + SetLength(Fitems, 0); + inherited Destroy; +end; + +destructor kt_folder_contents.Destroy; +var + I: Integer; +begin + for I := 0 to Length(Fitems)-1 do + if Assigned(Fitems[I]) then + Fitems[I].Free; + SetLength(Fitems, 0); + inherited Destroy; +end; + +destructor kt_metadata_field.Destroy; +var + I: Integer; +begin + for I := 0 to Length(Fselection)-1 do + if Assigned(Fselection[I]) then + Fselection[I].Free; + SetLength(Fselection, 0); + inherited Destroy; +end; + +destructor kt_metadata_fieldset.Destroy; +var + I: Integer; +begin + for I := 0 to Length(Ffields)-1 do + if Assigned(Ffields[I]) then + Ffields[I].Free; + SetLength(Ffields, 0); + inherited Destroy; +end; + +destructor kt_metadata_response.Destroy; +var + I: Integer; +begin + for I := 0 to Length(Fmetadata)-1 do + if Assigned(Fmetadata[I]) then + Fmetadata[I].Free; + SetLength(Fmetadata, 0); + inherited Destroy; +end; + +destructor kt_linked_document_response.Destroy; +var + I: Integer; +begin + for I := 0 to Length(Flinks)-1 do + if Assigned(Flinks[I]) then + Flinks[I].Free; + SetLength(Flinks, 0); + inherited Destroy; +end; + +destructor kt_document_transaction_history_response.Destroy; +var + I: Integer; +begin + for I := 0 to Length(Fhistory)-1 do + if Assigned(Fhistory[I]) then + Fhistory[I].Free; + SetLength(Fhistory, 0); + inherited Destroy; +end; + +destructor kt_document_version_history_response.Destroy; +var + I: Integer; +begin + for I := 0 to Length(Fhistory)-1 do + if Assigned(Fhistory[I]) then + Fhistory[I].Free; + SetLength(Fhistory, 0); + inherited Destroy; +end; + +initialization + InvRegistry.RegisterInterface(TypeInfo(KnowledgeTreePort), 'http://schemas.xmlsoap.org/soap/envelope/', ''); + InvRegistry.RegisterDefaultSOAPAction(TypeInfo(KnowledgeTreePort), 'http://schemas.xmlsoap.org/soap/envelope/#KTWebService#%operationName%'); + InvRegistry.RegisterExternalParamName(TypeInfo(KnowledgeTreePort), 'link_documents', 'type_', 'type'); + RemClassRegistry.RegisterXSClass(kt_response, 'urn:KnowledgeTree', 'kt_response'); + RemClassRegistry.RegisterExternalPropName(TypeInfo(kt_response), 'message_', 'message'); + RemClassRegistry.RegisterXSClass(kt_folder_detail, 'urn:KnowledgeTree', 'kt_folder_detail'); + RemClassRegistry.RegisterExternalPropName(TypeInfo(kt_folder_detail), 'message_', 'message'); + RemClassRegistry.RegisterXSInfo(TypeInfo(kt_folder_items), 'urn:KnowledgeTree', 'kt_folder_items'); + RemClassRegistry.RegisterXSClass(kt_folder_item, 'urn:KnowledgeTree', 'kt_folder_item'); + RemClassRegistry.RegisterXSClass(kt_folder_contents, 'urn:KnowledgeTree', 'kt_folder_contents'); + RemClassRegistry.RegisterExternalPropName(TypeInfo(kt_folder_contents), 'message_', 'message'); + RemClassRegistry.RegisterXSClass(kt_document_detail, 'urn:KnowledgeTree', 'kt_document_detail'); + RemClassRegistry.RegisterExternalPropName(TypeInfo(kt_document_detail), 'message_', 'message'); + RemClassRegistry.RegisterXSClass(kt_metadata_selection_item, 'urn:KnowledgeTree', 'kt_metadata_selection_item'); + RemClassRegistry.RegisterExternalPropName(TypeInfo(kt_metadata_selection_item), 'name_', 'name'); + RemClassRegistry.RegisterXSInfo(TypeInfo(kt_metadata_selection), 'urn:KnowledgeTree', 'kt_metadata_selection'); + RemClassRegistry.RegisterXSClass(kt_metadata_field, 'urn:KnowledgeTree', 'kt_metadata_field'); + RemClassRegistry.RegisterExternalPropName(TypeInfo(kt_metadata_field), 'name_', 'name'); + RemClassRegistry.RegisterXSInfo(TypeInfo(kt_metadata_fields), 'urn:KnowledgeTree', 'kt_metadata_fields'); + RemClassRegistry.RegisterXSClass(kt_metadata_fieldset, 'urn:KnowledgeTree', 'kt_metadata_fieldset'); + RemClassRegistry.RegisterXSInfo(TypeInfo(kt_metadata_fieldsets), 'urn:KnowledgeTree', 'kt_metadata_fieldsets'); + RemClassRegistry.RegisterXSClass(kt_metadata_response, 'urn:KnowledgeTree', 'kt_metadata_response'); + RemClassRegistry.RegisterExternalPropName(TypeInfo(kt_metadata_response), 'message_', 'message'); + RemClassRegistry.RegisterXSInfo(TypeInfo(kt_document_transitions), 'urn:KnowledgeTree', 'kt_document_transitions'); + RemClassRegistry.RegisterXSClass(kt_document_transitions_response, 'urn:KnowledgeTree', 'kt_document_transitions_response'); + RemClassRegistry.RegisterExternalPropName(TypeInfo(kt_document_transitions_response), 'message_', 'message'); + RemClassRegistry.RegisterXSClass(kt_document_transaction_history_item, 'urn:KnowledgeTree', 'kt_document_transaction_history_item'); + RemClassRegistry.RegisterXSClass(kt_linked_document, 'urn:KnowledgeTree', 'kt_linked_document'); + RemClassRegistry.RegisterXSInfo(TypeInfo(kt_linked_documents), 'urn:KnowledgeTree', 'kt_linked_documents'); + RemClassRegistry.RegisterXSClass(kt_linked_document_response, 'urn:KnowledgeTree', 'kt_linked_document_response'); + RemClassRegistry.RegisterExternalPropName(TypeInfo(kt_linked_document_response), 'message_', 'message'); + RemClassRegistry.RegisterXSInfo(TypeInfo(kt_document_transaction_history), 'urn:KnowledgeTree', 'kt_document_transaction_history'); + RemClassRegistry.RegisterXSClass(kt_document_transaction_history_response, 'urn:KnowledgeTree', 'kt_document_transaction_history_response'); + RemClassRegistry.RegisterExternalPropName(TypeInfo(kt_document_transaction_history_response), 'message_', 'message'); + RemClassRegistry.RegisterXSClass(kt_document_version_history_item, 'urn:KnowledgeTree', 'kt_document_version_history_item'); + RemClassRegistry.RegisterXSInfo(TypeInfo(kt_document_version_history), 'urn:KnowledgeTree', 'kt_document_version_history'); + RemClassRegistry.RegisterXSClass(kt_document_version_history_response, 'urn:KnowledgeTree', 'kt_document_version_history_response'); + RemClassRegistry.RegisterExternalPropName(TypeInfo(kt_document_version_history_response), 'message_', 'message'); + RemClassRegistry.RegisterXSInfo(TypeInfo(kt_document_types_array), 'urn:KnowledgeTree', 'kt_document_types_array'); + RemClassRegistry.RegisterXSClass(kt_document_types_response, 'urn:KnowledgeTree', 'kt_document_types_response'); + RemClassRegistry.RegisterExternalPropName(TypeInfo(kt_document_types_response), 'message_', 'message'); + +end. diff --git a/lib/documentmanagement/documentutil.inc.php b/lib/documentmanagement/documentutil.inc.php index 493977d..90d3ba8 100644 --- a/lib/documentmanagement/documentutil.inc.php +++ b/lib/documentmanagement/documentutil.inc.php @@ -898,7 +898,6 @@ class KTDocumentUtil { $sReason = ''; } - $oDocumentTransaction = new DocumentTransaction($oDocument, sprintf(_kt("Copied to folder \"%s\". %s"), $oDestinationFolder->getName(), $sReason), 'ktcore.transactions.copy'); $oDocumentTransaction->create(); @@ -906,6 +905,24 @@ class KTDocumentUtil { $oDocumentTransaction = new DocumentTransaction($oNewDocument, sprintf(_kt("Copied from original in folder \"%s\". %s"), $oSrcFolder->getName(), $sReason), 'ktcore.transactions.copy'); $oDocumentTransaction->create(); + + $oKTTriggerRegistry = KTTriggerRegistry::getSingleton(); + $aTriggers = $oKTTriggerRegistry->getTriggers('copyDocument', 'postValidate'); + foreach ($aTriggers as $aTrigger) { + $sTrigger = $aTrigger[0]; + $oTrigger = new $sTrigger; + $aInfo = array( + 'document' => $oNewDocument, + 'old_folder' => $oSrcFolder, + 'new_folder' => $oDestinationFolder, + ); + $oTrigger->setInfo($aInfo); + $ret = $oTrigger->postValidate(); + if (PEAR::isError($ret)) { + return $ret; + } + } + return $oNewDocument; } @@ -1013,15 +1030,15 @@ class KTDocumentUtil { return KTPermissionUtil::updatePermissionLookup($oDocument); } - + /** * Delete a selected version of the document. */ function deleteVersion($oDocument, $iVersionID, $sReason){ - + $oDocument =& KTUtil::getObject('Document', $oDocument); $oVersion =& KTDocumentMetadataVersion::get($iVersionID); - + $oStorageManager =& KTStorageManagerUtil::getSingleton(); global $default; @@ -1037,17 +1054,17 @@ class KTDocumentUtil { if (PEAR::isError($oVersion) || ($oVersion == false)) { return PEAR::raiseError(_kt('Invalid document version object.')); } - + $iContentId = $oVersion->getContentVersionId(); $oContentVersion = KTDocumentContentVersion::get($iContentId); - + if (PEAR::isError($oContentVersion) || ($oContentVersion == false)) { DBUtil::rollback(); return PEAR::raiseError(_kt('Invalid document content version object.')); } DBUtil::startTransaction(); - + // now delete the document version $res = $oStorageManager->deleteVersion($oVersion); if (PEAR::isError($res) || ($res == false)) { @@ -1064,11 +1081,11 @@ class KTDocumentUtil { return PEAR::raiseError(_kt('There was a problem deleting the document from storage.')); } - + // change status for the metadata version $oVersion->setStatusId(VERSION_DELETED); $oVersion->update(); - + // set the storage path to empty // $oContentVersion->setStoragePath(''); diff --git a/lib/upgrades/Ini.inc.php b/lib/upgrades/Ini.inc.php new file mode 100644 index 0000000..b83c6f9 --- /dev/null +++ b/lib/upgrades/Ini.inc.php @@ -0,0 +1,177 @@ +iniFile = $iniFile; + $this->read($iniFile); + } + + function read($iniFile) { + + $iniArray = file($iniFile); + $section = ''; + foreach($iniArray as $iniLine) { + $this->lineNum++; + $iniLine = trim($iniLine); + $firstChar = substr($iniLine, 0, 1); + if($firstChar == ';') { + if($section == ''){ + $this->cleanArray['_comment_'.$this->lineNum]=$iniLine; + }else { + $this->cleanArray[$section]['_comment_'.$this->lineNum]=$iniLine; + } + continue; + } + if($iniLine == '') { + if($section == ''){ + $this->cleanArray['_blankline_'.$this->lineNum]=''; + }else { + $this->cleanArray[$section]['_blankline_'.$this->lineNum]=''; + } + continue; + } + + if ($firstChar == '[' && substr($iniLine, -1, 1) == ']') { + $section = substr($iniLine, 1, -1); + $this->sections[] = $section; + } else { + $equalsPos = strpos($iniLine, '='); + if ($equalsPos > 0 && $equalsPos != sizeof($iniLine)) { + $key = trim(substr($iniLine, 0, $equalsPos)); + $value = trim(substr($iniLine, $equalsPos+1)); + if (substr($value, 1, 1) == '"' && substr( $value, -1, 1) == '"') { + $value = substr($value, 1, -1); + } + $this->cleanArray[$section][$key] = stripcslashes($value); + } else { + $this->cleanArray[$section][trim($iniLine)]=''; + } + } + } + return $this->cleanArray; + } + + function write($iniFile = "") { + + if(empty($iniFile)) { + $iniFile = $this->iniFile; + } + $fileHandle = fopen($iniFile, 'wb'); + foreach ($this->cleanArray as $section => $items) { + if (substr($section, 0, strlen('_blankline_')) === '_blankline_' ) { + fwrite ($fileHandle, "\r\n"); + continue; + } + if (substr($section, 0, strlen('_comment_')) === '_comment_' ) { + fwrite ($fileHandle, "$items\r\n"); + continue; + } + fwrite ($fileHandle, "[".$section."]\r\n"); + foreach ($items as $key => $value) { + if (substr($key, 0, strlen('_blankline_')) === '_blankline_' ) { + fwrite ($fileHandle, "\r\n"); + continue; + } + if (substr($key, 0, strlen('_comment_')) === '_comment_' ) { + fwrite ($fileHandle, "$value\r\n"); + continue; + } + + $value = addcslashes($value,''); + //fwrite ($fileHandle, $key.' = "'.$value."\"\r\n"); + fwrite ($fileHandle, $key.' = '.$value."\r\n"); + } + } + fclose($fileHandle); + } + + function itemExists($checkSection, $checkItem) { + + $this->exists = ''; + foreach($this->cleanArray as $section => $items) { + if($section == $checkSection) { + $this->exists = 'section'; + foreach ($items as $key => $value) { + if($key == $checkItem) { + return true; + } + } + } + } + return false; + } + + function addItem($addSection, $addItem, $value, $itemComment = '', $sectionComment = '') { + + if($this->itemExists($addSection, $addItem)) return false; + + if($this->exists != 'section') { + $this->cleanArray['_blankline_'.$this->lineNum++]=''; + if(!empty($sectionComment)) $this->cleanArray['_comment_'.$this->lineNum++] = '; '.$sectionComment; + } + if(!empty($itemComment)) { + $this->cleanArray[$addSection]['_comment_'.$this->lineNum++] = '; '.$itemComment; + } + $this->cleanArray[$addSection][$addItem] = stripcslashes($value); + return true; + } + +} +/* +// USAGE EXAMPLE + +if(file_exists('../../../config.ini')) { + + $ini = new Ini(); + $ini->addItem('Section1', 'NewItem1', 'Some Text1', 'Item1 Comment', 'Section1 Comment'); + $ini->addItem('Section1', 'NewItem1.2', 'Some Text1.2', 'Item1.2 Comment'); + $ini->addItem('Section1', 'NewItem1.3', 'Some Text1.3', 'Item1.3 Comment'); + $ini->addItem('Section1', 'NewItem1.4', 'Some Text1.4', 'Item1.4 Comment'); + $ini->addItem('Section2', 'NewItem2', 'Some Text2', 'Item2 Comment'); + $ini->addItem('Section2', 'NewItem2.1', 'Some Text2.1'); + $ini->addItem('Section3', 'NewItem3', 'Some Text3', 'Item3 Comment', 'Section3 Comment'); + $ini->addItem('Section4', 'NewItem4', 'Some Text4', 'Item4 Comment'); + $ini->write(); + +} +*/ +?> diff --git a/plugins/generalmetadata/GeneralMetadataDashlet.php b/plugins/generalmetadata/GeneralMetadataDashlet.php deleted file mode 100644 index cc46c31..0000000 --- a/plugins/generalmetadata/GeneralMetadataDashlet.php +++ /dev/null @@ -1,80 +0,0 @@ -sTitle = _kt('General Metadata Search'); - } - - /** - * Check to see if user is active - * - * @param object $oUser - * @return boolean - */ - function is_active($oUser) { - $this->oUser = $oUser; - return true; - } - - /** - * Render function for template - * - * @return unknown - */ - function render() { - $oTemplating =& KTTemplating::getSingleton(); - $oTemplate = $oTemplating->loadTemplate('GeneralMetadata/dashlet'); - - $oRegistry =& KTPluginRegistry::getSingleton(); - $oPlugin =& $oRegistry->getPlugin('ktcore.generalmetadata.plugin'); - $url = $oPlugin->getPagePath('GeneralMetadataPage'); - - $aTemplateData = array( - 'context' => $this, - 'url' => $url, - ); - return $oTemplate->render($aTemplateData); - } -} -?> diff --git a/plugins/generalmetadata/GeneralMetadataPage.php b/plugins/generalmetadata/GeneralMetadataPage.php deleted file mode 100644 index d73b997..0000000 --- a/plugins/generalmetadata/GeneralMetadataPage.php +++ /dev/null @@ -1,128 +0,0 @@ -aBreadcrumbs[] = array('url' => 'dashboard.php', 'name' => _kt('Dashboard')); - $this->aBreadcrumbs[] = array('name' => _kt('General Metadata Search')); - - $sTitle = _kt('Search Results'); - $this->oPage->setBreadcrumbDetails($sTitle); - - - $aCriteriaSet = array( - 'join'=>'AND', - 'subgroup'=>array( - 0=>array( - 'join'=>'AND', - 'values'=>array( - 1=>array( - 'data'=>array( - 'ktcore.criteria.generalmetadata'=>$searchable_text, - 'ktcore.criteria.generalmetadata_not'=>0 - ), - 'type'=>'ktcore.criteria.generalmetadata' - ) - ) - ) - ) - ); - - - $this->browseType = "Folder"; - $sSearch = md5(serialize($aCriteriaSet)); - $_SESSION['boolean_search'][$sSearch] = $aCriteriaSet; - - $collection = new AdvancedCollection; - $oColumnRegistry = KTColumnRegistry::getSingleton(); - $aColumns = $oColumnRegistry->getColumnsForView('ktcore.views.search'); - $collection->addColumns($aColumns); - - // set a view option - $aTitleOptions = array( - 'documenturl' => $GLOBALS['KTRootUrl'] . '/view.php', - ); - $collection->setColumnOptions('ktcore.columns.title', $aTitleOptions); - $collection->setColumnOptions('ktcore.columns.selection', array( - 'rangename' => 'selection', - 'show_folders' => true, - 'show_documents' => true, - )); - - $aOptions = $collection->getEnvironOptions(); // extract data from the environment - - $aOptions['return_url'] = KTUtil::addQueryStringSelf("action=performSearch&boolean_search_id=" . urlencode($sSearch)); - $aOptions['empty_message'] = _kt("No documents or folders match this query."); - $aOptions['is_browse'] = true; - - $collection->setOptions($aOptions); - $collection->setQueryObject(new BooleanSearchQuery($aCriteriaSet)); - - $oTemplating =& KTTemplating::getSingleton(); - $oTemplate = $oTemplating->loadTemplate("kt3/browse"); - $aTemplateData = array( - "context" => $this, - "collection" => $collection, - "custom_title" => $sTitle, - "params" => $aParams, - "joins" => $aJoins, - 'isEditable' => true, - "boolean_search" => $sSearch, - 'bulkactions' => KTBulkActionUtil::getAllBulkActions(), - 'browseutil' => new KTBrowseUtil(), - 'returnaction' => 'booleanSearch', - 'returndata' => $sSearch, - - ); - return $oTemplate->render($aTemplateData); - } -} -?> \ No newline at end of file diff --git a/plugins/generalmetadata/GeneralMetadataPlugin.php b/plugins/generalmetadata/GeneralMetadataPlugin.php deleted file mode 100644 index ec3dbad..0000000 --- a/plugins/generalmetadata/GeneralMetadataPlugin.php +++ /dev/null @@ -1,71 +0,0 @@ -sFriendlyName = _kt('General Metadata Search Plugin'); - return $res; - } - - /** - * Setup function for plugin - * - */ - function setup() { - // Register plugin components - $this->registerCriterion('GeneralMetadataCriterion', 'ktcore.criteria.generalmetadata', KT_LIB_DIR . '/browse/Criteria.inc'); - $this->registerDashlet('GeneralMetadataDashlet', 'ktcore.generalmetadata.dashlet', 'GeneralMetadataDashlet.php'); - $this->registerPage('GeneralMetadataPage', 'GeneralMetadataPage', __FILE__); - - $oTemplating =& KTTemplating::getSingleton(); - $oTemplating->addLocation('General Metadata Search', '/plugins/generalmetadata/templates'); - } - } -$oPluginRegistry =& KTPluginRegistry::getSingleton(); -$oPluginRegistry->registerPlugin('GeneralMetadataPlugin', 'ktcore.generalmetadata.plugin', __FILE__); \ No newline at end of file diff --git a/plugins/generalmetadata/templates/GeneralMetadata/dashlet.smarty b/plugins/generalmetadata/templates/GeneralMetadata/dashlet.smarty deleted file mode 100644 index 6e0614b..0000000 --- a/plugins/generalmetadata/templates/GeneralMetadata/dashlet.smarty +++ /dev/null @@ -1,15 +0,0 @@ -
- -
-{if (!empty($saved_searches))} -
-

{i18n}Saved Searches{/i18n}

-{foreach item=oSearch from=$saved_searches} -{i18n}Saved Search{/i18n}: getId()}">{$oSearch->getName()}
-{/foreach} - - -{/if} \ No newline at end of file diff --git a/plugins/ktcore/KTDocumentActions.php b/plugins/ktcore/KTDocumentActions.php index bb18ced..a1735fa 100644 --- a/plugins/ktcore/KTDocumentActions.php +++ b/plugins/ktcore/KTDocumentActions.php @@ -1242,25 +1242,6 @@ class KTDocumentCopyAction extends KTDocumentAction { $this->commitTransaction(); - // FIXME do we need to refactor all trigger usage into the util function? - $oKTTriggerRegistry = KTTriggerRegistry::getSingleton(); - $aTriggers = $oKTTriggerRegistry->getTriggers('copyDocument', 'postValidate'); - foreach ($aTriggers as $aTrigger) { - $sTrigger = $aTrigger[0]; - $oTrigger = new $sTrigger; - $aInfo = array( - 'document' => $oNewDoc, - 'old_folder' => $this->oDocumentFolder, - 'new_folder' => $data['browse'], - ); - $oTrigger->setInfo($aInfo); - $ret = $oTrigger->postValidate(); - } - - //$aOptions = array('user' => $oUser); - //$oDocumentTransaction = & new DocumentTransaction($oNewDoc, 'Document copied from old version.', 'ktcore.transactions.create', $aOptions); - //$res = $oDocumentTransaction->create(); - $_SESSION['KTInfoMessage'][] = _kt('Document copied.'); controllerRedirect('viewDocument', 'fDocumentId=' . $oNewDoc->getId()); diff --git a/plugins/ktcore/folder/Permissions.php b/plugins/ktcore/folder/Permissions.php index 6a6e1d2..c7bc10a 100644 --- a/plugins/ktcore/folder/Permissions.php +++ b/plugins/ktcore/folder/Permissions.php @@ -132,7 +132,7 @@ class KTFolderPermissionsAction extends KTFolderAction { // from a folder. if ($oInherited->getId() !== $this->oFolder->getId()) { $iInheritedFolderId = $oInherited->getId(); - $sInherited = join(' » ', $oInherited->getPathArray()); + $sInherited = join(' > ', $oInherited->getPathArray()); } // only allow inheritance if not inherited, -and- folders is editable $bInheritable = $bEdit && ($oInherited->getId() !== $this->oFolder->getId()); diff --git a/plugins/ktstandard/SearchDashlet.php b/plugins/ktstandard/SearchDashlet.php deleted file mode 100644 index b0d13df..0000000 --- a/plugins/ktstandard/SearchDashlet.php +++ /dev/null @@ -1,56 +0,0 @@ -sTitle = _kt('Search Dashlet'); - } - - function render() { - $oTemplating =& KTTemplating::getSingleton(); - $oTemplate = $oTemplating->loadTemplate('ktstandard/searchdashlet/dashlet'); - - $aSearches = KTSavedSearch::getSearches(); - // empty on error. - if (PEAR::isError($aSearches)) { - $aSearches = array(); - } - - - $aTemplateData = array( - 'savedsearches' => $aSearches, - ); - return $oTemplate->render($aTemplateData); - } -} - -?> \ No newline at end of file diff --git a/plugins/ktstandard/SearchDashletPlugin.php b/plugins/ktstandard/SearchDashletPlugin.php deleted file mode 100644 index 5959fcc..0000000 --- a/plugins/ktstandard/SearchDashletPlugin.php +++ /dev/null @@ -1,56 +0,0 @@ -sFriendlyName = _kt('Search Dashlet Plugin'); - return $res; - } - - function setup() { - $this->registerDashlet('SearchDashlet', 'ktstandard.searchdashlet.dashlet', 'SearchDashlet.php'); - - require_once(KT_LIB_DIR . "/templating/templating.inc.php"); - $oTemplating =& KTTemplating::getSingleton(); - $oTemplating->addLocation('searchdashlet', '/plugins/searchdashlet/templates'); - } -} - -$oPluginRegistry =& KTPluginRegistry::getSingleton(); -$oPluginRegistry->registerPlugin('SearchDashletPlugin', 'ktstandard.searchdashlet.plugin', __FILE__); -?> diff --git a/plugins/search2/Search2Portlet.php b/plugins/search2/Search2Portlet.php index 80a77d2..8fb3386 100644 --- a/plugins/search2/Search2Portlet.php +++ b/plugins/search2/Search2Portlet.php @@ -6,6 +6,7 @@ class Search2Portlet extends KTPortlet function Search2Portlet() { parent::KTPortlet(_kt("Search")); + $this->bActive = true; } function render() diff --git a/plugins/tagcloud/TagCloudDashlet.php b/plugins/tagcloud/TagCloudDashlet.php index 9bc87d3..c043073 100644 --- a/plugins/tagcloud/TagCloudDashlet.php +++ b/plugins/tagcloud/TagCloudDashlet.php @@ -127,7 +127,6 @@ class TagCloudDashlet extends KTBaseDashlet { } list($where, $params, $joins) = KTSearchUtil::permissionToSQL($this->oUser, null); - $sql = " SELECT TW.tag, count(*) as freq @@ -135,7 +134,6 @@ class TagCloudDashlet extends KTBaseDashlet { document_tags DT INNER JOIN tag_words TW ON DT.tag_id=TW.id WHERE DT.document_id in (SELECT D.id FROM documents D $joins WHERE $where) GROUP BY TW.tag"; - $tags = DBUtil::getResultArray( array($sql,$params) diff --git a/plugins/tagcloud/TagCloudRedirectPage.php b/plugins/tagcloud/TagCloudRedirectPage.php index 254e9ff..2036ea4 100644 --- a/plugins/tagcloud/TagCloudRedirectPage.php +++ b/plugins/tagcloud/TagCloudRedirectPage.php @@ -103,7 +103,8 @@ class TagCloudRedirectPage extends KTStandardDispatcher { $aOptions = $collection->getEnvironOptions(); // extract data from the environment - $aOptions['return_url'] = KTUtil::addQueryString('dashboard.php', false); + //$aOptions['return_url'] = KTUtil::addQueryString('dashboard.php', false); + $aOptions['return_url'] = KTUtil::addQueryString('TagCloudRedirection&tag='. $searchable_text, false ); $aOptions['empty_message'] = _kt('No documents or folders match this query.'); $aOptions['is_browse'] = true;