Index: openacs-4/contrib/packages/classified-ads/tcl/classified-ads-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/classified-ads/tcl/classified-ads-procs.tcl,v diff -u -r1.3 -r1.4 --- openacs-4/contrib/packages/classified-ads/tcl/classified-ads-procs.tcl 19 Jul 2003 01:48:45 -0000 1.3 +++ openacs-4/contrib/packages/classified-ads/tcl/classified-ads-procs.tcl 23 Jul 2003 21:08:19 -0000 1.4 @@ -1,745 +1,749 @@ ad_library { - Classified Ads Procs +Classified Ads Procs - @author Deds Castillo (deds@infiniteinfo.com) - @creation-date 2002-10-08 - @cvs-id $Id$ +@author Deds Castillo (deds@infiniteinfo.com) +@creation-date 2002-10-08 +@cvs-id $Id$ } -namespace eval classified-ads { - ad_proc -public package_key {} { - Returns the package key - } { - return "classified-ads" - } +namespace eval classified-ads {} +ad_proc -public classified-ads::package_key {} { + Returns the package key +} { + return "classified-ads" +} - ad_proc -public is_instantiated {} { - Returns 1 if classified-ads is instantiated, 0 otherwise - } { - return [ad_decode [apm_num_instances [package_key]] 0 0 1] - } +ad_proc -public classified-ads::is_instantiated {} { + Returns 1 if classified-ads is instantiated, 0 otherwise +} { + return [ad_decode [apm_num_instances [package_key]] 0 0 1] +} - ad_proc -public main_keyword_exists_p {} { - Returns the keyword id of the main category for the package, 0 if not yet created - } { - # These are magic values - set heading "[package_key]-main-category" - set description "$heading Main Category, this is where all classified ads categories are rooted" +ad_proc -public classified-ads::main_keyword_exists_p {} { + Returns the keyword id of the main category for the package, 0 if not yet created +} { + # These are magic values + set heading "[package_key]-main-category" + set description "$heading Main Category, this is where all classified ads categories are rooted" - return [db_string get_main_keyword {} -default 0] - } + return [db_string get_main_keyword {} -default 0] +} - ad_proc -public root_folder_exists_p {} { - Returns the folder id of the classified ads root folder, 0 if not yet created - } { - # These are magic values - set name "[package_key]" - set label "[package_key]" - set description "$name Root Folder, all classified ads items go here" +ad_proc -public classified-ads::root_folder_exists_p {} { + Returns the folder id of the classified ads root folder, 0 if not yet created +} { + # These are magic values + set name "[package_key]" + set label "[package_key]" + set description "$name Root Folder, all classified ads items go here" - return [db_string get_root_folder {} -default 0] - - } + return [db_string get_root_folder {} -default 0] - ad_proc -public get_root_folder_id {} { - Returns the folder id of the classified ads root folder, error if none - } { - set folder_id [root_folder_exists_p] +} - if {!$folder_id} { - ad_return_error "Root Folder not found" \ - "The root folder for [package_key] was not found. The datamodel might not be properly installed. Did you restart the server after installation?" - ad_script_abort - } +ad_proc -public classified-ads::get_root_folder_id {} { + Returns the folder id of the classified ads root folder, error if none +} { + set folder_id [root_folder_exists_p] - return $folder_id - } + if {!$folder_id} { + ad_return_error "Root Folder not found" \ + "The root folder for [package_key] was not found. The datamodel might not be properly installed. Did you restart the server after installation?" + ad_script_abort + } + return $folder_id +} - ad_proc -public get_folder_id { - {-package_id} - } { - Returns the folder_id for an instance of classified ads - @param package_id The package id of this classified ads instance. - Default to current instance if none passed. - } { - if {![exists_and_not_null package_id]} { - set package_id [ad_conn package_id] - } +ad_proc -public classified-ads::get_folder_id { + {-package_id} +} { + Returns the folder_id for an instance of classified ads - return [db_string select_folder_id {}] - } + @param package_id The package id of this classified ads instance. + Default to current instance if none passed. +} { + if {![exists_and_not_null package_id]} { + set package_id [ad_conn package_id] + } + return [db_string select_folder_id {}] +} - ad_proc -public get_mounted_packages {} { - Returns a list of mounted classified-ads packages - } { - set package_key [package_key] - return [db_list select_packages {}] - } - ad_proc -public get_content_type { - {-item_id:required} - } { +ad_proc -public classified-ads::get_mounted_packages {} { + Returns a list of mounted classified-ads packages +} { + set package_key [package_key] + return [db_list select_packages {}] +} + +ad_proc -public classified-ads::get_content_type { + {-item_id:required} +} { Gets the content type of a given item - } { - return [db_string select_type {}] - } +} { + return [db_string select_type {}] +} - ad_proc -public get_table_name { - {-content_type:required} - } { - Gets the table name of one content type - } { - return [db_string select_table_name {}] - } +ad_proc -public classified-ads::get_table_name { + {-content_type:required} +} { + Gets the table name of one content type +} { + return [db_string select_table_name {}] +} - ad_proc -public register_content_type { - {-folder_id:required} - {-content_type:required} - {-include_subtypes "f"} - } { - Registers a given content type to a particular folder - } { - return [db_list register_content_type {}] - } +ad_proc -public classified-ads::register_content_type { + {-folder_id:required} + {-content_type:required} + {-include_subtypes "f"} +} { + Registers a given content type to a particular folder +} { + return [db_list register_content_type {}] +} - ad_proc -public create_package_folder { - {-root_folder_id:required} - {-package_id:required} - } { - Creates a content revision folder for one instance of classified ads +ad_proc -public classified-ads::create_package_folder { + {-root_folder_id:required} + {-package_id:required} +} { + Creates a content revision folder for one instance of classified ads - @param root_folder_id The root folder id for the whole classified ads package - @param package_id The package id of the instance whose folder is to be created - } { - set name "[package_key]-$package_id" - set label "$name folder" - set description "Container folder for one instance of classified-ads" + @param root_folder_id The root folder id for the whole classified ads package + @param package_id The package id of the instance whose folder is to be created +} { + set name "[package_key]-$package_id" + set label "$name folder" + set description "Container folder for one instance of classified-ads" - db_transaction { - set new_folder_id [db_exec_plsql create_folder {}] - db_exec_plsql associate_package {} - } + db_transaction { + set new_folder_id [db_exec_plsql create_folder {}] + db_exec_plsql associate_package {} + } - return $new_folder_id - } + return $new_folder_id +} - ad_proc -public create_ca_item { - {-item_id_element:required} - {-parent_id} +ad_proc -public classified-ads::create_ca_item { + {-item_id_element:required} + {-parent_id} {-category_id} - {-content_type:required} - {-form_id:required} - {-title_column "title"} - {-description_column "description"} - {-data_column "data"} - } { - Creates a classified ads item. This is generic enough to: - 1. handle items that are either derived from content_revision or not - 2. dynamically generate insert statements for extension tables - 3. dynamically generate insert statements to handle generic attributes - 4. create new revisions as appropriate + {-content_type:required} + {-form_id:required} + {-title_column "title"} + {-description_column "description"} + {-data_column "data"} +} { + Creates a classified ads item. This is generic enough to: + 1. handle items that are either derived from content_revision or not + 2. dynamically generate insert statements for extension tables + 3. dynamically generate insert statements to handle generic attributes + 4. create new revisions as appropriate @author Deds Castillo @author Roberto Mello (rmello@fslc.usu.edu) - - @param item_id_element The name of the form element that should be used as the item id - @param content_type The type of the item being inserted - @param form_id The ID of the form that contains the the name/value pairs - } { - set package_id [ad_conn package_id] + @param item_id_element The name of the form element that should be used as the item id + @param content_type The type of the item being inserted + @param form_id The ID of the form that contains the the name/value pairs - if {![info exists parent_id]} { - set parent_id [get_folder_id -package_id $package_id] - } +} { + set package_id [ad_conn package_id] - set creation_user [ad_conn user_id] - set creation_ip [ad_conn peeraddr] + if {![info exists parent_id]} { + set parent_id [get_folder_id -package_id $package_id] + } - # DEDS: FIXME - for now we are assuming required fields are filtered - # out by the validation in the form procedures. i think we should - # double check it here again and barf if one of them is missing + set creation_user [ad_conn user_id] + set creation_ip [ad_conn peeraddr] - # get the item id, barf if not present + # DEDS: FIXME - for now we are assuming required fields are filtered + # out by the validation in the form procedures. i think we should + # double check it here again and barf if one of them is missing - if {[template::element::exists $form_id $item_id_element]} { - set item_id [template::element::get_value $form_id $item_id_element] - } else { - ad_return_complaint 1 "
  • Passed in item id not found" - ad_script_abort - } + # get the item id, barf if not present - # check if this is a subclass of content_revision + if {[template::element::exists $form_id $item_id_element]} { + set item_id [template::element::get_value $form_id $item_id_element] + } else { + ad_return_complaint 1 "
  • Passed in item id not found" + ad_script_abort + } - set cr_subclass_p [is_subclass -content_type $content_type -parent_type content_revision] - set content_item [get_supertype -content_type $content_type] + # check if this is a subclass of content_revision - set name "$content_type -- $item_id" - set title [template::element::get_value $form_id $title_column] + set cr_subclass_p [is_subclass -content_type $content_type -parent_type content_revision] + set content_item [get_supertype -content_type $content_type] - if {[empty_string_p $title]} { - # make sure there is always a title - set title $name - } + set name "$content_type -- $item_id" + set title [template::element::get_value $form_id $title_column] - set description [template::element::get_value $form_id $description_column] + if {[empty_string_p $title]} { + # make sure there is always a title + set title $name + } - if {[template::element::exists $form_id $data_column]} { - set data [template::element::get_value $form_id $data_column] - } + set description [template::element::get_value $form_id $description_column] - # do everything in a transaction + if {[template::element::exists $form_id $data_column]} { + set data [template::element::get_value $form_id $data_column] + } - db_transaction { - # insert the content item + # do everything in a transaction - set object_id [db_exec_plsql insert_content_item {}] - set cr_item_id $object_id + db_transaction { + # insert the content item - if {$cr_subclass_p} { - set object_id [db_exec_plsql insert_content_revision {}] - } + set object_id [db_exec_plsql insert_content_item {}] + set cr_item_id $object_id - # RBM: If a category was passed, assign the ad to it. - - if {[info exists category_id]} { - db_exec_plsql assign_item_to_category {} - } + if {$cr_subclass_p} { + set object_id [db_exec_plsql insert_content_revision {}] + } - # DEDS: FIXME - this only supports one table - # fix it so that it can span multiple tables - # - # get the type specific attributes + # RBM: If a category was passed, assign the ad to it. - set type_specific_attr_list [get_attributes -content_type $content_type -storage "type_specific"] - - if {[llength $type_specific_attr_list]} { - # we always reference the item_id - set name_list [list $item_id_element] - set value_list [list $object_id] - set type_specific_bind_vars [ns_set create] + if {[info exists category_id]} { + db_exec_plsql assign_item_to_category {} + } + + # DEDS: FIXME - this only supports one table + # fix it so that it can span multiple tables + # + # get the type specific attributes + + set type_specific_attr_list [get_attributes -content_type $content_type -storage "type_specific"] + + if {[llength $type_specific_attr_list]} { + # we always reference the item_id + set name_list [list $item_id_element] + set value_list [list $object_id] + set type_specific_bind_vars [ns_set create] - foreach one_attribute $type_specific_attr_list { - set column_name [ns_set get $one_attribute column_name] - set table_name [ns_set get $one_attribute table_name] - - if {[template::element::exists $form_id $column_name]} { - lappend name_list $column_name - lappend value_list ":$column_name" - set one_value [template::element::get_value $form_id $column_name] + foreach one_attribute $type_specific_attr_list { + set column_name [ns_set get $one_attribute column_name] + set table_name [ns_set get $one_attribute table_name] + + if {[template::element::exists $form_id $column_name]} { + lappend name_list $column_name + lappend value_list ":$column_name" + set one_value [template::element::get_value $form_id $column_name] - if {[string match "date" [ns_set get $one_attribute datatype]]} { - set one_value [classified-ads::widgets::date_widget_to_sql -date $one_value] - } + if {[string match "date" [ns_set get $one_attribute datatype]]} { + set one_value [classified-ads::widgets::date_widget_to_sql -date $one_value] + } - ns_set put $type_specific_bind_vars $column_name $one_value + ns_set put $type_specific_bind_vars $column_name $one_value - } else { - set default_value [ns_set get $one_attribute default_value] + } else { + set default_value [ns_set get $one_attribute default_value] - if {![empty_string_p $default_value]} { - lappend name_list $column_name - lappend value_list ":$column_name" - ns_set put $type_specific_bind_vars $column_name $default_value - } - } - } + if {![empty_string_p $default_value]} { + lappend name_list $column_name + lappend value_list ":$column_name" + ns_set put $type_specific_bind_vars $column_name $default_value + } + } + } - # create the insert statement for type specific attributes + # create the insert statement for type specific attributes - set plsql_query "insert into $table_name ([join $name_list ", "]) values ([join $value_list ", "])" - - # insert the type specific data + set plsql_query "insert into $table_name ([join $name_list ", "]) values ([join $value_list ", "])" - db_dml insert_data {} -bind $type_specific_bind_vars - ns_set free $type_specific_bind_vars - } - - # get the generic attributes + # insert the type specific data - set generic_attr_list [get_attributes -content_type $content_type -storage "generic"] - - if {[llength $generic_attr_list]} { - - foreach one_attribute $generic_attr_list { - set attribute_id [ns_set get $one_attribute attribute_id] - set column_name [ns_set get $one_attribute column_name] - set datatype [ns_set get $one_attribute datatype] - - if {[template::element::exists $form_id $column_name]} { - set attr_value [template::element::get_value $form_id $column_name] + db_dml insert_data {} -bind $type_specific_bind_vars + ns_set free $type_specific_bind_vars + } + + # get the generic attributes + + set generic_attr_list [get_attributes -content_type $content_type -storage "generic"] + + if {[llength $generic_attr_list]} { + + foreach one_attribute $generic_attr_list { + set attribute_id [ns_set get $one_attribute attribute_id] + set column_name [ns_set get $one_attribute column_name] + set datatype [ns_set get $one_attribute datatype] + + if {[template::element::exists $form_id $column_name]} { + set attr_value [template::element::get_value $form_id $column_name] - if {[string match "date" $datatype]} { - set attr_value [classified-ads::widgets::date_widget_to_sql -date $attr_value] - } - } else { - set default_value [ns_set get $one_attribute default_value] - - if {![empty_string_p $default_value]} { - set attr_value $default_value - } else { - set attr_value "" - } - } + if {[string match "date" $datatype]} { + set attr_value [classified-ads::widgets::date_widget_to_sql -date $attr_value] + } + } else { + set default_value [ns_set get $one_attribute default_value] - insert_generic_value -object_id $item_id -attribute_id $attribute_id -attr_value $attr_value - } - } - } on_error { - ad_return_complaint 1 "
  • $errmsg" - ad_script_abort - } + if {![empty_string_p $default_value]} { + set attr_value $default_value + } else { + set attr_value "" + } + } - return $item_id - - } + insert_generic_value -object_id $item_id -attribute_id $attribute_id -attr_value $attr_value + } + } + } on_error { + ad_return_complaint 1 "
  • $errmsg" + ad_script_abort + } - ad_proc -public edit_ca_item { - {-item_id_element:required} - {-form_id:required} - {-title_column "title"} - {-description_column "description"} - {-data_column "data"} - {-revision_id} - } { - Edits a classified ads item. + return $item_id - @param item_id_element The name of the form element that should be used as the item id - @param form_id The ID of the form that contains the the name/value pairs - @param title_column The element name in the form that will be used as title of this content - @param description_column The element name in the form that will be used as description of this content - } { +} - set creation_user [ad_conn user_id] - set creation_ip [ad_conn peeraddr] +ad_proc -public classified-ads::edit_ca_item { + {-item_id_element:required} + {-form_id:required} + {-title_column "title"} + {-description_column "description"} + {-data_column "data"} + {-revision_id} +} { + Edits a classified ads item. - # DEDS: FIXME - for now we are assuming required fields are filtered - # out by the validation in the form procedures. i think we should - # double check it here again and barf if one of them is missing + @param item_id_element The name of the form element that should be used as the item id + @param form_id The ID of the form that contains the the name/value pairs + @param title_column The element name in the form that will be used as title of this content + @param description_column The element name in the form that will be used as description of this content +} { - # get the item id, barf if not present + set creation_user [ad_conn user_id] + set creation_ip [ad_conn peeraddr] - if {[template::element::exists $form_id $item_id_element]} { - set item_id [template::element::get_value $form_id $item_id_element] - } else { - ad_return_complaint 1 "
  • passed in item id not found" - ad_script_abort - } + # DEDS: FIXME - for now we are assuming required fields are filtered + # out by the validation in the form procedures. i think we should + # double check it here again and barf if one of them is missing - set create_revision_p 0 + # get the item id, barf if not present - # check if this is a subclass of content_revision + if {[template::element::exists $form_id $item_id_element]} { + set item_id [template::element::get_value $form_id $item_id_element] + } else { + ad_return_complaint 1 "
  • passed in item id not found" + ad_script_abort + } - set content_type [get_content_type -item_id $item_id] - set cr_subclass_p [is_subclass -content_type $content_type -parent_type content_revision] + set create_revision_p 0 - if {$cr_subclass_p} { - if {[parameter::get -parameter create_new_ad_revision_p -default 0]} { - set create_revision_p 1 - } - if {[info exists revision_id]} { - set object_id $revision_id - } else { - set object_id [get_latest_revision -item_id $item_id] - } + # check if this is a subclass of content_revision - } else { - set object_id $item_id - } + set content_type [get_content_type -item_id $item_id] + set cr_subclass_p [is_subclass -content_type $content_type -parent_type content_revision] - set name "$content_type -- $item_id" - set title [template::element::get_value $form_id $title_column] + if {$cr_subclass_p} { + if {[parameter::get -parameter create_new_ad_revision_p -default 0]} { + set create_revision_p 1 + } + if {[info exists revision_id]} { + set object_id $revision_id + } else { + set object_id [get_latest_revision -item_id $item_id] + } - if {[empty_string_p $title]} { - # make sure there is always a title - set title $name - } + } else { + set object_id $item_id + } + + set name "$content_type -- $item_id" + set title [template::element::get_value $form_id $title_column] + + if {[empty_string_p $title]} { + # make sure there is always a title + set title $name + } - set description [template::element::get_value $form_id $description_column] + set description [template::element::get_value $form_id $description_column] - if {[template::element::exists $form_id $data_column]} { - set data [template::element::get_value $form_id $data_column] - } + if {[template::element::exists $form_id $data_column]} { + set data [template::element::get_value $form_id $data_column] + } - # do everything in a transaction + # do everything in a transaction - db_transaction { - # DEDS: FIXME - this only supports one table - # fix it so that it can span multiple tables - - if {$create_revision_p} { - set object_id [db_exec_plsql insert_content_revision {}] - } elseif {$cr_subclass_p} { - # DEDS: FIXME - this is straghtforward update. we should be using cr api. - db_dml update_content_revision {} - } - - # get the type specific attributes - set type_specific_attr_list [get_attributes -content_type $content_type -storage "type_specific"] - - if {[llength $type_specific_attr_list]} { - # we always reference the item_id - set update_list [list] - set name_list [list $item_id_element] - set value_list [list $object_id] - set type_specific_bind_vars [ns_set create] - - foreach one_attribute $type_specific_attr_list { - set column_name [ns_set get $one_attribute column_name] - set table_name [ns_set get $one_attribute table_name] - set datatype [ns_set get $one_attribute datatype] - - if {[template::element::exists $form_id $column_name]} { - lappend name_list $column_name - lappend value_list ":$column_name" - lappend update_list "$column_name = :$column_name" - set one_value [template::element::get_value $form_id $column_name] - if {[string match "date" $datatype]} { - set one_value [classified-ads::widgets::date_widget_to_sql -date $one_value] - } - ns_set put $type_specific_bind_vars $column_name $one_value - } - } + db_transaction { + # DEDS: FIXME - this only supports one table + # fix it so that it can span multiple tables - ns_set put $type_specific_bind_vars item_id $object_id + if {$create_revision_p} { + set object_id [db_exec_plsql insert_content_revision {}] - # create the update statement for type specific attributes + } elseif {$cr_subclass_p} { + # DEDS: FIXME - this is straghtforward update. we should be using cr api. + db_dml update_content_revision {} + } - if {$create_revision_p} { - set plsql_query "insert into $table_name ([join $name_list ", "]) values ([join $value_list ", "])" - } else { - set plsql_query "update $table_name set [join $update_list ", "] where $item_id_element = :item_id" - } - - # update the type specific data + # Get the type specific attributes - db_dml update_data {} -bind $type_specific_bind_vars - ns_set free $type_specific_bind_vars - } - - # get the generic attributes - - set generic_attr_list [get_attributes -content_type $content_type -storage "generic"] - - if {[llength $generic_attr_list]} { - foreach one_attribute $generic_attr_list { - set attribute_id [ns_set get $one_attribute attribute_id] - set column_name [ns_set get $one_attribute column_name] - set datatype [ns_set get $one_attribute datatype] - - if {[template::element::exists $form_id $column_name]} { - set attr_value [template::element::get_value $form_id $column_name] + set type_specific_attr_list [get_attributes -content_type $content_type -storage "type_specific"] + + if {[llength $type_specific_attr_list]} { + # + # We always reference the item_id + # - if {[string match "date" $datatype]} { - set attr_value [classified-ads::widgets::date_widget_to_sql -date $attr_value] - } - } + set update_list [list] + set name_list [list $item_id_element] + set value_list [list $object_id] + set type_specific_bind_vars [ns_set create] + + foreach one_attribute $type_specific_attr_list { + set column_name [ns_set get $one_attribute column_name] + set table_name [ns_set get $one_attribute table_name] + set datatype [ns_set get $one_attribute datatype] - if {$create_revision_p} { - insert_generic_value -object_id $object_id -attribute_id $attribute_id -attr_value $attr_value - } else { - update_generic_value -object_id $object_id -attribute_id $attribute_id -attr_value $attr_value - } - - } - } - } on_error { - ad_return_complaint 1 "
  • $errmsg" - ad_script_abort - } - - return $object_id - } + if {[template::element::exists $form_id $column_name]} { + lappend name_list $column_name + lappend value_list ":$column_name" + lappend update_list "$column_name = :$column_name" + set one_value [template::element::get_value $form_id $column_name] + if {[string match "date" $datatype]} { + set one_value [classified-ads::widgets::date_widget_to_sql -date $one_value] + } + ns_set put $type_specific_bind_vars $column_name $one_value + } + } - ad_proc -public is_subclass { - {-content_type:required} - {-parent_type:required} - } { - Returns 1 if an object type is a subclass of another - - @param content_type The object type to check - @param parent_type The supertype class the proc test against - } { - return [ad_decode [db_string test_subclass {}] f 0 1] - } + ns_set put $type_specific_bind_vars item_id $object_id + # create the update statement for type specific attributes - ad_proc -public get_attributes { - {-content_type:required} - {-package_id} - {-storage "all"} - } { - Returns a list of ns_sets of the attributes for one content type - - @param content_type This is the content type whose attributes we get - @param package_id Only the attributes belonging to this package is retrieved. - Defaults to current package. - @param storage Only the attributes who belong to this storage type are retrieved. - Can be "type_specific", "generic", or "all". - } { - if {![exists_and_not_null package_id]} { - set package_id [ad_conn package_id] - } + if {$create_revision_p} { + set plsql_query "insert into $table_name ([join $name_list ", "]) values ([join $value_list ", "])" + } else { + set plsql_query "update $table_name set [join $update_list ", "] where $item_id_element = :item_id" + } - if {![string equal $storage "all"]} { - set storage_stub "and storage = '$storage'" - } else { - set storage_stub "" - } + # update the type specific data + + db_dml update_data {} -bind $type_specific_bind_vars + ns_set free $type_specific_bind_vars + } - return [db_list_of_ns_sets select_attributes {}] - } + # get the generic attributes + + set generic_attr_list [get_attributes -content_type $content_type -storage "generic"] + + if {[llength $generic_attr_list]} { + foreach one_attribute $generic_attr_list { + set attribute_id [ns_set get $one_attribute attribute_id] + set column_name [ns_set get $one_attribute column_name] + set datatype [ns_set get $one_attribute datatype] - ad_proc -public get_attribute_names { - {-item_id} - {-storage "all"} - } { - Returns a list of lists of the attribute names for one item - - @param package_id The item id whose attribute names we get - } { - if {![exists_and_not_null package_id]} { - set package_id [ad_conn package_id] - } + if {[template::element::exists $form_id $column_name]} { + set attr_value [template::element::get_value $form_id $column_name] - if {![string equal $storage "all"]} { - set storage_stub "and storage = '$storage'" - } else { - set storage_stub "" - } + if {[string match "date" $datatype]} { + set attr_value [classified-ads::widgets::date_widget_to_sql -date $attr_value] + } + } - set content_type [get_content_type -item_id $item_id] - return [db_list_of_lists select_names {}] - } + if {$create_revision_p} { + insert_generic_value -object_id $object_id -attribute_id $attribute_id -attr_value $attr_value + } else { + update_generic_value -object_id $object_id -attribute_id $attribute_id -attr_value $attr_value + } + } + } + } on_error { + ad_return_complaint 1 "
  • $errmsg" + ad_script_abort + } - ad_proc -public get_attribute_values { - {-item_id:required} - {-item_id_element:required} - {-storage "all"} - {-revision_id} - } { + return $object_id +} - Returns a list of lists of the attribute values for one item - - @param item_id The ID of the object whose values we retrieve - @param storage Only the attribute values who belong to this storage type are retrieved. - Can be "type_specific", "generic", or "all". - } { - set values_list [list] - set cr_subclass_p [is_subclass -content_type [get_content_type \ - -item_id $item_id] \ - -parent_type content_revision] +ad_proc -public classified-ads::is_subclass { + {-content_type:required} + {-parent_type:required} +} { + Returns 1 if an object type is a subclass of another - if {![info exists revision_id] && $cr_subclass_p} { - set revision_id [get_latest_revision -item_id $item_id] - } + @param content_type The object type to check + @param parent_type The supertype class the proc test against +} { + return [ad_decode [db_string test_subclass {}] f 0 1] +} - if {[string match $storage "type_specific"] || [string match $storage "all"]} { - set table_name [get_table_name -content_type [get_content_type -item_id $item_id]] - set names_value_list [get_attribute_names -item_id $item_id -storage type_specific] - set names_list [list] - foreach one_name_value $names_value_list { - lappend names_list [lindex $one_name_value 0] - } - - if {$cr_subclass_p} { - set query_string "select [join $names_list ", "] - from $table_name - where $item_id_element = '$revision_id'" - } else { - set query_string "select [join $names_list ", "] - from $table_name - where $item_id_element = '$item_id'" - } - - db_1row select_values {} -column_array type_specific_row - - foreach one_name_value $names_value_list { - set datatype [lindex $one_name_value 1] - set one_value $type_specific_row([lindex $one_name_value 0]) - - if {[string match "date" $datatype] && ![empty_string_p $one_value]} { - set one_value [classified-ads::widgets::sql_to_date_widget -sql_date $one_value -format "YYYY-MM-DD"] - } - - lappend values_list [list [lindex $one_name_value 0] $one_value] - } - } +ad_proc -public classified-ads::get_attributes { + {-content_type:required} + {-package_id} + {-storage "all"} +} { + Returns a list of ns_sets of the attributes for one content type - if {[string match $storage "generic"] || [string match $storage "all"]} { - if {$cr_subclass_p} { - set query_string "select coalesce(aa.column_name, aa.attribute_name) as column_name, - cav.attr_value, - aa.datatype - from acs_attributes aa, - ca_attribute_values cav - where aa.attribute_id = cav.attribute_id and - cav.object_id = '$revision_id'" - } else { - set query_string "select coalesce(aa.column_name, aa.attribute_name) as column_name, - cav.attr_value, - aa.datatype - from acs_attributes aa, - ca_attribute_values cav - where aa.attribute_id = cav.attribute_id and - cav.object_id = '$item_id'" - } - - set generic_list [db_list_of_lists select_values {}] - - foreach one_name $generic_list { - set datatype [lindex $one_name_value 2] - set one_value [lindex $one_name_value 1] - - if {[string match "date" $datatype] && ![empty_string_p $one_value]} { - set one_value [classified-ads::widgets::sql_to_date_widget -sql_date $one_value -format "YYYY-MM-DD"] - } - lappend values_list [list [lindex $one_name 0] $one_value] - } - } + @param content_type This is the content type whose attributes we get + @param package_id Only the attributes belonging to this package is retrieved. + Defaults to current package. + @param storage Only the attributes who belong to this storage type are retrieved. + Can be "type_specific", "generic", or "all". +} { + if {![exists_and_not_null package_id]} { + set package_id [ad_conn package_id] + } - return $values_list - } + if {![string equal $storage "all"]} { + set storage_stub "and storage = '$storage'" + } else { + set storage_stub "" + } - ad_proc -public get_supertype { - {-content_type:required} - } { - Returns the direct ancestor of one content type - - @param content_type This is the content type whose ancestor we get - } { - return [db_string select_supertype {}] - } + return [db_list_of_ns_sets select_attributes {}] +} +ad_proc -public classified-ads::get_attribute_names { + {-item_id} + {-storage "all"} +} { + Returns a list of lists of the attribute names for one item - ad_proc -public insert_generic_value { - {-object_id:required} - {-attribute_id:required} - {-attr_value ""} - } { + @param package_id The item id whose attribute names we get +} { + if {![exists_and_not_null package_id]} { + set package_id [ad_conn package_id] + } - Inserts one value for a generic attribute - - @param object_id The object id of the objects who owns this value - @param attribute_id The id of the attribute that will contain a new value - @param attr_value The associated value of this attribute for this object - + if {![string equal $storage "all"]} { + set storage_stub "and storage = '$storage'" + } else { + set storage_stub "" + } - } { - return [db_exec_plsql insert_value {}] - } + set content_type [get_content_type -item_id $item_id] + return [db_list_of_lists select_names {}] +} - ad_proc -public update_generic_value { - {-object_id:required} - {-attribute_id:required} - {-attr_value ""} - } { - Updates one value for a generic attribute - - @param object_id The object id of the objects who owns this value - @param attribute_id The id of the attribute that will be updated - @param attr_value The associated value of this attribute for this object - } { - return [db_exec_plsql update_value {}] - } +ad_proc -public classified-ads::get_attribute_values { + {-item_id:required} + {-item_id_element:required} + {-storage "all"} + {-revision_id} +} { + Returns a list of lists of the attribute values for one item - ad_proc -public get_latest_revision { - {-item_id:required} - } { - Returns the latest revision for one item - - @param item_id The id of the item that we want to get the latest revision - } { - return [db_string get_revision {} -default 0] - } + @param item_id The ID of the object whose values we retrieve + @param storage Only the attribute values who belong to this storage type are retrieved. + Can be "type_specific", "generic", or "all". +} { + set values_list [list] + set cr_subclass_p [is_subclass -content_type [get_content_type \ + -item_id $item_id] \ + -parent_type content_revision] - ad_proc -public get_content { - {-revision_id:required} - } { - Returns the content of one item - - @param revision_id The id of the revision to get the data from - } { - return [db_string select_content {}] - } + if {![info exists revision_id] && $cr_subclass_p} { + set revision_id [get_latest_revision -item_id $item_id] + } + if {[string match $storage "type_specific"] || [string match $storage "all"]} { + set table_name [get_table_name -content_type [get_content_type -item_id $item_id]] + set names_value_list [get_attribute_names -item_id $item_id -storage type_specific] + set names_list [list] - ad_proc -public context_bar { - {-node_id} - args - } { - Returns a context bar relative to classified ads - - @param node_id if provided, then we work up from this node - } { - if { ![info exists node_id] } { - set node_id [ad_conn node_id] - } + foreach one_name_value $names_value_list { + lappend names_list [lindex $one_name_value 0] + } - set context [list] - - db_foreach context {} { - lappend context [list $url $object_name] - } - - if { [string match admin/* [ad_conn extra_url]] } { - lappend context [list "[ad_conn package_url]admin/" "Administration"] - } - - if {[llength $args] == 0} { - # fix last element to just be literal string - - set context [lreplace $context end end [lindex [lindex $context end] 1]] - } - - return [ad_context_bar_html [concat $context $args]] - } + if {$cr_subclass_p} { + set query_string "select [join $names_list ", "] + from $table_name + where $item_id_element = '$revision_id'" + } else { + set query_string "select [join $names_list ", "] + from $table_name + where $item_id_element = '$item_id'" + } - ad_proc validate_isbn { isbn } { - Does a simple check-digit verigication of isbn. - @author Ben Bytheway - } { - set isbn [string trim $isbn] - regsub -all {(\D&^Xi&^x)} $isbn "" isbn - - if {![regexp {^(\d|X|x){10}$} $isbn]} { - return 1 - } - - set check 0 - set test_isbn [split $isbn ""] - - if {[lindex $test_isbn end] == "x" || [lindex $test_isbn end] == "X"} { - set test_isbn [lreplace $test_isbn end end 10 ] - } - - for {set i 0} {$i <= 9} {incr i} { - set digit [lindex $test_isbn $i] - set check [expr ($digit * (10 - $i)) + $check] - } + db_1row select_values {} -column_array type_specific_row - set check [expr $check % 11] + foreach one_name_value $names_value_list { + set datatype [lindex $one_name_value 1] + set one_value $type_specific_row([lindex $one_name_value 0]) - if { !$check && [string index $isbn 0] != 6} { - return 0 - } else { - return 1 - } - } + if {[string match "date" $datatype] && ![empty_string_p $one_value]} { + set one_value [classified-ads::widgets::sql_to_date_widget -sql_date $one_value -format "YYYY-MM-DD"] + } + + lappend values_list [list [lindex $one_name_value 0] $one_value] + } + } + + # RBM: FIXME - We shouldn't generate the entire query here? + + if {[string match $storage "generic"] || [string match $storage "all"]} { + if {$cr_subclass_p} { + set query_string "select coalesce(aa.column_name, aa.attribute_name) as column_name, + cav.attr_value, + aa.datatype + from acs_attributes aa, + ca_attribute_values cav + where aa.attribute_id = cav.attribute_id and + cav.object_id = '$revision_id'" + } else { + set query_string "select coalesce(aa.column_name, aa.attribute_name) as column_name, + cav.attr_value, + aa.datatype + from acs_attributes aa, + ca_attribute_values cav + where aa.attribute_id = cav.attribute_id and + cav.object_id = '$item_id'" + } + + set generic_list [db_list_of_lists select_values {}] + + foreach one_name $generic_list { + set datatype [lindex $one_name_value 2] + set one_value [lindex $one_name_value 1] + + if {[string match "date" $datatype] && ![empty_string_p $one_value]} { + set one_value [classified-ads::widgets::sql_to_date_widget -sql_date $one_value -format "YYYY-MM-DD"] + } + lappend values_list [list [lindex $one_name 0] $one_value] + } + } + + return $values_list } + +ad_proc -public classified-ads::get_supertype { + {-content_type:required} +} { + Returns the direct ancestor of one content type + + @param content_type This is the content type whose ancestor we get +} { + return [db_string select_supertype {}] +} + + +ad_proc -public classified-ads::insert_generic_value { + {-object_id:required} + {-attribute_id:required} + {-attr_value ""} +} { + Inserts one value for a generic attribute + + @param object_id The object id of the objects who owns this value + @param attribute_id The id of the attribute that will contain a new value + @param attr_value The associated value of this attribute for this object +} { + return [db_exec_plsql insert_value {}] +} + + +ad_proc -public classified-ads::update_generic_value { + {-object_id:required} + {-attribute_id:required} + {-attr_value ""} +} { + Updates one value for a generic attribute + + @param object_id The object id of the objects who owns this value + @param attribute_id The id of the attribute that will be updated + @param attr_value The associated value of this attribute for this object +} { + return [db_exec_plsql update_value {}] +} + + +ad_proc -public classified-ads::get_latest_revision { + {-item_id:required} +} { + Returns the latest revision for one item + + @param item_id The id of the item that we want to get the latest revision +} { + return [db_string get_revision {} -default 0] +} + + +ad_proc -public classified-ads::get_content { + {-revision_id:required} +} { + Returns the content of one item + + @param revision_id The id of the revision to get the data from +} { + return [db_string select_content {}] +} + + +ad_proc -public classified-ads::context_bar { + {-node_id} + args +} { + Returns a context bar relative to classified ads + + @param node_id if provided, then we work up from this node +} { + if { ![info exists node_id] } { + set node_id [ad_conn node_id] + } + + set context [list] + + db_foreach context {} { + lappend context [list $url $object_name] + } + + if { [string match admin/* [ad_conn extra_url]] } { + lappend context [list "[ad_conn package_url]admin/" "Administration"] + } + + if {[llength $args] == 0} { + # fix last element to just be literal string + + set context [lreplace $context end end [lindex [lindex $context end] 1]] + } + + return [ad_context_bar_html [concat $context $args]] +} + +ad_proc validate_isbn { isbn } { + Does a simple check-digit verigication of isbn. + @author Ben Bytheway +} { + set isbn [string trim $isbn] + regsub -all {(\D&^Xi&^x)} $isbn "" isbn + + if {![regexp {^(\d|X|x){10}$} $isbn]} { + return 1 + } + + set check 0 + set test_isbn [split $isbn ""] + + if {[lindex $test_isbn end] == "x" || [lindex $test_isbn end] == "X"} { + set test_isbn [lreplace $test_isbn end end 10 ] + } + + for {set i 0} {$i <= 9} {incr i} { + set digit [lindex $test_isbn $i] + set check [expr ($digit * (10 - $i)) + $check] + } + + set check [expr $check % 11] + + if { !$check && [string index $isbn 0] != 6} { + return 0 + } else { + return 1 + } +}