cmis_server 1.2.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/cmis_server/atom_pub/entries_controller.rb +2 -1
  3. data/app/controllers/cmis_server/atom_pub/folder_collection_controller.rb +55 -11
  4. data/app/controllers/cmis_server/atom_pub/query_controller.rb +44 -16
  5. data/app/controllers/cmis_server/atom_pub/service_documents_controller.rb +1 -1
  6. data/app/services/cmis_server/discovery_service.rb +58 -9
  7. data/app/services/cmis_server/navigation_service.rb +62 -3
  8. data/app/services/cmis_server/object_service.rb +112 -13
  9. data/app/views/cmis_server/atom_pub/entries/_cmis_folder_links.atom_entry.builder +1 -1
  10. data/app/views/cmis_server/atom_pub/entries/_object_entry.atom_entry.builder +4 -3
  11. data/app/views/cmis_server/atom_pub/entries/type_entry.atom_entry.builder +1 -1
  12. data/app/views/cmis_server/atom_pub/feeds/feed.atom_feed.builder +3 -0
  13. data/app/views/cmis_server/atom_pub/query_results_feed.atom_feed.builder +59 -0
  14. data/app/views/cmis_server/atom_pub/queryable_types_feed.atom_feed.builder +35 -0
  15. data/app/views/cmis_server/atom_pub/service_documents/_workspace.atom_service.builder +1 -1
  16. data/config/initializers/cmis_core_configuration.rb +31 -8
  17. data/lib/cmis_server/atom_pub/entry_parser.rb +57 -22
  18. data/lib/cmis_server/cmis_object.rb +32 -2
  19. data/lib/cmis_server/configuration.rb +4 -3
  20. data/lib/cmis_server/connectors/CORE_CONNECTOR_QUERIES.md +180 -0
  21. data/lib/cmis_server/connectors/core_connector.rb +189 -69
  22. data/lib/cmis_server/constants.rb +3 -2
  23. data/lib/cmis_server/document_adapter.rb +135 -0
  24. data/lib/cmis_server/document_object.rb +1 -1
  25. data/lib/cmis_server/engine.rb +95 -0
  26. data/lib/cmis_server/exceptions.rb +19 -0
  27. data/lib/cmis_server/folder_adapter.rb +126 -0
  28. data/lib/cmis_server/property.rb +40 -4
  29. data/lib/cmis_server/query/parser.rb +11 -0
  30. data/lib/cmis_server/query/{parser.racc.rb → parser_racc.rb} +2 -2
  31. data/lib/cmis_server/query/{parser.rex.rb → parser_rex.rb} +6 -1
  32. data/lib/cmis_server/query/simple_parser.rb +276 -0
  33. data/lib/cmis_server/query/statement.rb +3 -389
  34. data/lib/cmis_server/query/statement.rb.bak +395 -0
  35. data/lib/cmis_server/query.rb +11 -2
  36. data/lib/cmis_server/renderable_collection.rb +23 -2
  37. data/lib/cmis_server/repository.rb +1 -1
  38. data/lib/cmis_server/version.rb +1 -1
  39. data/lib/cmis_server.rb +13 -0
  40. metadata +12 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c87c1fab52b4c8aa922033238d51f43d3c25a6e5f6c0092724cef97472578f31
4
- data.tar.gz: 57d772e88f5289328d115f9db9639ad6e5d8a1a9a0dcab2a4f4306ac67c61104
3
+ metadata.gz: 9bc9d9ec2eaf839148dcb6721c119047890413d107a85595a74bc35cbb53bd84
4
+ data.tar.gz: 8872e2dd94ccc9012f78de2d1481b32efaccebe36dfa3f363d37f19b9f666ccd
5
5
  SHA512:
6
- metadata.gz: 91a949552ebbbfdaf96ca799c81748883d12a0751451240683f374e0e389724a303d505823d694859a9bdcd6bda44184129ce303537b8343e6041312de99a972
7
- data.tar.gz: 54a256c2f164ea708bcbbdad775abae2aca79bea1281e2f188c133e134f0fcbe0ef944c4913750b5753e20e174395f06e0bc75756552c8de397d6b5107c649c2
6
+ metadata.gz: ff9ac2fa277eac8327b9aa4e59b0756abdfc8df9a801dfd43d72419ecb202d8650403f0385bce7770b45536bf59380d214215cf2576ce4b7ab3e261640f407fd
7
+ data.tar.gz: 71165260bafa6571c3a0b85426c911cb01256e29573c0f2e8aba8206bcf5e5cf9fedc570798763b2d195b56cbfd9278909be6a3a116cf1317d38f8ce5433fdea
@@ -17,7 +17,8 @@ module CmisServer
17
17
  end
18
18
 
19
19
  def destroy
20
-
20
+ object_service.delete_object(id)
21
+ head :no_content
21
22
  end
22
23
 
23
24
  protected
@@ -9,56 +9,100 @@ module CmisServer
9
9
 
10
10
 
11
11
  def get_children
12
- service =NavigationService.new(@repository, context)
13
- response=service.get_children(params[:id], max_items: max_items_param, order_by: params[:orderBy])
12
+
13
+ begin
14
+ service =NavigationService.new(@repository, current_context)
15
+ response=service.get_children(params[:id], max_items: max_items_param, order_by: params[:orderBy])
16
+
17
+ rescue => e
18
+ Rails.logger.error "FolderCollectionController#get_children - Error: #{e.message}"
19
+ Rails.logger.error "FolderCollectionController#get_children - Backtrace: #{e.backtrace.first(10).join("\n")}"
20
+ raise e
21
+ end
14
22
 
15
- @collection=RenderableCollection.new(base_object: CmisServer::FolderAdapter.class_adapter(context: @context).find(params[:id]),
16
- items: response[:objects])
23
+ # Utiliser le connecteur pour récupérer le dossier parent
24
+ connector = CmisServer::Connectors::ConnectorFactory.create_connector(
25
+ user: current_context.current_user
26
+ )
27
+ parent_object = connector.find_object_by_id(params[:id])
28
+
29
+ # Gérer le cas spécial du root folder
30
+ if params[:id] == 'root_folder' || params[:id] == 'root_folder_id' || params[:id] == 'core_root' || params[:id] == 'root'
31
+ # Pour le root, utiliser directement nil comme parent_folder
32
+ # car c'est un dossier virtuel qui n'a pas besoin d'être dans la collection
33
+ parent_folder = nil
34
+ elsif parent_object
35
+ # C'est un objet Core normal, le convertir en objet CMIS
36
+ adapter = CmisServer::FolderAdapter.new(nil, context: current_context)
37
+ parent_folder = adapter.find(parent_object.id.to_s)
38
+ else
39
+ raise CmisServer::ObjectNotFound.new("Folder '#{params[:id]}' not found")
40
+ end
41
+
42
+ # Si nous avons une erreur avec les objets, retourner une collection vide
43
+ items = response[:objects] || []
44
+
45
+
46
+ @collection=RenderableCollection.new(base_object: parent_folder,
47
+ items: items)
17
48
  render 'cmis_server/atom_pub/feeds/feed', formats: :atom_feed
18
49
  end
19
50
 
20
51
  def create_children
21
52
  #Check if Document exists
22
53
  begin
54
+
23
55
  if request_entry_parser.cmis_object_id
24
56
  #We move the document to the folder
25
57
 
26
58
  else
27
59
  #We create the document
28
60
  object_type=request_entry_parser.object_type
29
- service =ObjectService.new(@repository, context)
61
+
62
+ # Protection si object_type est nil
63
+ if object_type.nil?
64
+ Rails.logger.error "Object type is nil, cannot determine type"
65
+ raise "Invalid object type in request"
66
+ end
67
+
68
+ service =ObjectService.new(@repository, current_context)
30
69
  case object_type.base_type.id
31
70
  when "cmis:document"
32
71
  id =service.create_document(request_entry_parser.object_properties, folder_id: params[:id], content_stream: request_entry_parser.content_stream)
33
- @object=CmisServer::DocumentAdapter::ClassAdapter.new(context: @context).find(id).to_renderable_object
72
+ @object=CmisServer::DocumentAdapter.class_adapter(context: current_context).find(id).to_renderable_object
34
73
  render 'cmis_server/atom_pub/entries/object_entry', formats: :atom_entry, status: :created
35
74
  when "cmis:folder"
36
- id =service.create_folder(request_entry_parser.object_properties)
37
- @object=CmisServer::FolderAdapter.class_adapter(context: @context).find(id).to_renderable_object
75
+ id =service.create_folder(request_entry_parser.object_properties, parent_folder_id: params[:id])
76
+ @object=CmisServer::FolderAdapter.class_adapter(context: current_context).find(id).to_renderable_object
38
77
  render 'cmis_server/atom_pub/entries/object_entry', formats: :atom_entry, status: :created
39
78
  when "cmis:policy"
40
79
  # Implémentation future de la gestion des politiques
41
80
  when "cmis:item"
42
81
  id =service.create_item(request_entry_parser.object_properties)
43
- @object=CmisServer::ItemAdapter.class_adapter(context: @context).find(id).to_renderable_object
82
+ @object=CmisServer::ItemAdapter.class_adapter(context: current_context).find(id).to_renderable_object
44
83
  render 'cmis_server/atom_pub/entries/object_entry', formats: :atom_entry, status: :created
45
84
  else
46
85
  raise "Unknown type #{object_type.base_type.id}"
47
86
  end
48
87
  end
49
88
  rescue CmisServer::ObjectService::DuplicateFile => e
89
+ Rails.logger.error "DuplicateFile error: #{e.message}"
50
90
  @object=e.duplicate.to_renderable_object
51
91
  render 'cmis_server/atom_pub/entries/object_entry', formats: :atom_entry, status: :conflict
92
+ rescue => e
93
+ Rails.logger.error "Error in create_children: #{e.message}"
94
+ Rails.logger.error "Backtrace: #{e.backtrace.first(10).join("\n")}"
95
+ raise e
52
96
  end
53
97
  end
54
98
 
55
99
  def get_descendants
56
- service=NavigationService.new(@repository, context)
100
+ service=NavigationService.new(@repository, current_context)
57
101
  service.get_descendants(params[:id])
58
102
  end
59
103
 
60
104
  def destroy
61
- service = ObjectService.new(@repository, context)
105
+ service = ObjectService.new(@repository, current_context)
62
106
  service.delete_object(params[:id])
63
107
  head :no_content
64
108
  end
@@ -13,8 +13,9 @@ module CmisServer
13
13
 
14
14
  begin
15
15
  discovery_service = CmisServer::DiscoveryService.new(@repository, current_context)
16
+
16
17
  results = discovery_service.query(
17
- statement: query_data[:statement],
18
+ query_data[:statement],
18
19
  search_all_versions: query_data[:search_all_versions],
19
20
  include_allowable_actions: query_data[:include_allowable_actions],
20
21
  include_relationships: query_data[:include_relationships],
@@ -23,19 +24,31 @@ module CmisServer
23
24
  skip_count: query_data[:skip_count]
24
25
  )
25
26
 
27
+
26
28
  respond_to do |format|
27
29
  format.atom_feed { render "cmis_server/atom_pub/query_results_feed", locals: { results: results } }
28
30
  format.json { render json: format_query_results_for_json(results) }
29
31
  end
30
32
  rescue => e
31
- render_error(e)
33
+ Rails.logger.error "QueryController#query: Error occurred: #{e.class} - #{e.message}"
34
+ Rails.logger.error "QueryController#query: Backtrace:\n#{e.backtrace.join("\n")}"
35
+
36
+ # Add detailed error message to response
37
+ respond_to do |format|
38
+ format.atom_feed do
39
+ render xml: { error: { type: e.class.name, message: e.message, backtrace: e.backtrace[0..5] } }.to_xml(root: 'error'), status: 500
40
+ end
41
+ format.json do
42
+ render json: { error: { type: e.class.name, message: e.message, backtrace: e.backtrace[0..5] } }, status: 500
43
+ end
44
+ end
32
45
  end
33
46
  end
34
47
 
35
48
  # GET /query/types
36
49
  def queryable_types
37
50
  repository = repository_from_request
38
- queryable_types = repository.types.select { |_, type| type.queryable }
51
+ queryable_types = CmisServer::TypeRegistry.types.select { |_, type| type.queryable }
39
52
 
40
53
  respond_to do |format|
41
54
  format.atom_feed { render "cmis_server/atom_pub/queryable_types_feed", locals: { types: queryable_types } }
@@ -105,23 +118,38 @@ module CmisServer
105
118
  end
106
119
 
107
120
  def parse_atom_pub_query_request
108
- doc = Nokogiri::XML(request.body.read)
109
- doc.remove_namespaces!
110
-
111
- {
112
- statement: doc.at_xpath("//statement")&.text || params[:q],
113
- search_all_versions: doc.at_xpath("//searchAllVersions")&.text == "true",
114
- include_allowable_actions: doc.at_xpath("//includeAllowableActions")&.text == "true",
115
- include_relationships: doc.at_xpath("//includeRelationships")&.text || "none",
116
- rendition_filter: doc.at_xpath("//renditionFilter")&.text || "",
117
- max_items: (doc.at_xpath("//maxItems")&.text || params[:maxItems] || 100).to_i,
118
- skip_count: (doc.at_xpath("//skipCount")&.text || params[:skipCount] || 0).to_i
119
- }
121
+ # Rails parse automatiquement le JSON et le met dans params
122
+ if params[:query]
123
+ # Les données sont déjà parsées par Rails
124
+ {
125
+ statement: params[:query][:statement] || params[:statement],
126
+ search_all_versions: params[:query][:searchAllVersions] == true,
127
+ include_allowable_actions: params[:query][:includeAllowableActions] == true,
128
+ include_relationships: params[:query][:includeRelationships] || "none",
129
+ rendition_filter: params[:query][:renditionFilter] || "",
130
+ max_items: (params[:query][:maxItems] || 100).to_i,
131
+ skip_count: (params[:query][:skipCount] || 0).to_i
132
+ }
133
+ else
134
+ # Fallback pour le XML si nécessaire
135
+ doc = Nokogiri::XML(request.body.read)
136
+ doc.remove_namespaces!
137
+
138
+ {
139
+ statement: doc.at_xpath("//statement")&.text || params[:q],
140
+ search_all_versions: doc.at_xpath("//searchAllVersions")&.text == "true",
141
+ include_allowable_actions: doc.at_xpath("//includeAllowableActions")&.text == "true",
142
+ include_relationships: doc.at_xpath("//includeRelationships")&.text || "none",
143
+ rendition_filter: doc.at_xpath("//renditionFilter")&.text || "",
144
+ max_items: (doc.at_xpath("//maxItems")&.text || params[:maxItems] || 100).to_i,
145
+ skip_count: (doc.at_xpath("//skipCount")&.text || params[:skipCount] || 0).to_i
146
+ }
147
+ end
120
148
  end
121
149
 
122
150
  def format_query_results_for_json(results)
123
151
  {
124
- results: results[:objects].map { |obj| obj.to_json },
152
+ results: (results[:query_results] || results[:objects] || []).map { |obj| obj.to_json },
125
153
  hasMoreItems: results[:has_more_items],
126
154
  numItems: results[:num_items]
127
155
  }
@@ -8,7 +8,7 @@ module CmisServer
8
8
 
9
9
 
10
10
  def service_document
11
- @repository=Repository.find('my_repo')
11
+ @repository=Repository.find('core_repository')
12
12
  render 'cmis_server/atom_pub/service_documents/service_document', formats: :atom_service
13
13
  end
14
14
 
@@ -1,3 +1,5 @@
1
+ require 'ostruct'
2
+
1
3
  module CmisServer
2
4
  class DiscoveryService
3
5
 
@@ -8,23 +10,70 @@ module CmisServer
8
10
 
9
11
 
10
12
  def query(statement, search_all_versions: false, include_relationships: :none, rendition_filter: "cmis:none", include_allowable_actions: false, max_items: 10, skip_count: 0)
11
-
12
- query_statement=CmisServer::Query::Parser.parse(statement)
13
+
14
+ begin
15
+
16
+ query_statement=CmisServer::Query::Parser.parse(statement)
17
+
18
+ rescue => e
19
+ Rails.logger.error "Error in DiscoveryService.query: #{e.class} - #{e.message}"
20
+ Rails.logger.error e.backtrace.join("\n")
21
+ raise
22
+ end
13
23
 
14
24
  #Verify that there is only one Table
15
25
  table=query_statement.query_expression.from.tables.first
16
- raise "Join are not supported" unless table.is_a? CmisServer::Query::Statement::Table
17
- target_klass=TypeAdapter.find(table.name)
26
+ # La vérification est déjà faite dans le lambda is_a?
27
+ raise "Join are not supported" unless table.is_a?.call(CmisServer::Query::Statement::Table)
28
+
29
+ # Récupérer le type CMIS
30
+ target_type=CmisServer::TypeRegistry.get_type(table.name)
31
+ unless target_type
32
+ raise ::CmisServer::InvalidArgument.new("Type '#{table.name}' not found")
33
+ end
18
34
 
19
- objects=target_klass.adapter_class.class_adapter(context: @context).where(query_statement.query_expression.where.to_h, limit: 10, offset: 0)
35
+ # Utiliser le connecteur pour faire la recherche
36
+ connector = CmisServer::Connectors::ConnectorFactory.create_connector(
37
+ user: @context.current_user
38
+ )
39
+
40
+ # Convertir les conditions WHERE en conditions de recherche
41
+ conditions = query_statement.query_expression.where ? query_statement.query_expression.where.to_h : {}
42
+
43
+ # Rechercher selon le type
44
+ objects = case target_type.base_id.to_s
45
+ when 'cmis:document'
46
+ connector.find_documents(conditions.merge(page: (skip_count / max_items) + 1, per_page: max_items))
47
+ when 'cmis:folder'
48
+ connector.find_folders(conditions.merge(page: (skip_count / max_items) + 1, per_page: max_items))
49
+ else
50
+ []
51
+ end
52
+
53
+ # Convertir en objets renderable
54
+ renderable_objects = objects.map do |obj|
55
+ # Utiliser les adapters pour créer les objets CMIS correctement
56
+ if target_type.base_id.to_s == 'cmis:document' && obj.is_a?(::Doc)
57
+ adapter = CmisServer::DocumentAdapter.new(nil, context: @context)
58
+ cmis_doc = adapter.find(obj.id.to_s)
59
+ cmis_doc.to_renderable_object
60
+ elsif target_type.base_id.to_s == 'cmis:folder' && (obj.is_a?(::Tagset) || (obj.respond_to?(:is_space) && obj.is_space))
61
+ adapter = CmisServer::FolderAdapter.new(nil, context: @context)
62
+ cmis_folder = adapter.find(obj.id.to_s)
63
+ cmis_folder.to_renderable_object
64
+ else
65
+ # Fallback pour les types non supportés
66
+ Rails.logger.warn "DiscoveryService: Unsupported object type for query result: #{obj.class}"
67
+ nil
68
+ end
69
+ end.compact
20
70
 
21
71
  {
22
- query_results: objects.map { |o| o.to_renderable_object },
23
- has_more_items: false, #ToDO
24
- num_items: nil, #ToDO
72
+ query_results: renderable_objects,
73
+ has_more_items: objects.count == max_items, # Si on a le max, il y en a peut-être d'autres
74
+ num_items: nil, # Non supporté pour l'instant
25
75
  }
26
76
 
27
-
28
77
  end
29
78
 
30
79
  end
@@ -8,11 +8,70 @@ module CmisServer
8
8
 
9
9
  def get_children(folder_id, max_items: 10, skip_count: 0, order_by: {'cmis:creationDate' => :asc}, filter: [], include_relationships: :none, rendition_filter: "cmis:none", include_allowable_actions: false, include_path_segment: false, with_object: false)
10
10
 
11
- folder=CmisServer::FolderAdapter.class_adapter(context: @context).find(folder_id)
11
+ # Utiliser le connecteur pour récupérer le dossier et ses enfants
12
+ connector = CmisServer::Connectors::ConnectorFactory.create_connector(
13
+ user: @context.current_user
14
+ )
15
+
16
+ # Récupérer le dossier parent
17
+ folder = connector.find_object_by_id(folder_id)
18
+ unless folder
19
+ raise CmisServer::ObjectNotFound.new(debug_data: "Folder '#{folder_id}' not found")
20
+ end
21
+
22
+ # Déterminer quels enfants récupérer selon le type de dossier
23
+ children = []
24
+
25
+ # Si c'est le dossier racine, retourner les espaces favoris de l'utilisateur
26
+ if folder_id == 'core_root' || folder_id == 'root_folder' || folder_id == 'root_folder_id' || folder_id == 'root'
27
+ # Les espaces favoris sont les "dossiers racines" de l'utilisateur dans Core
28
+ children = connector.find_root_folders()
29
+ else
30
+ # Pour un espace spécifique, récupérer:
31
+ # 1. Les documents dans cet espace
32
+ documents = connector.find_documents({'space_ids' => [folder_id]})
33
+ # 2. Les sous-espaces (si applicable)
34
+ sub_spaces = connector.find_folders({'parent_id' => folder_id})
35
+
36
+ children = documents + sub_spaces
37
+ end
38
+
39
+ # Convertir en objets renderable
40
+ renderable_objects = children.map do |obj|
41
+ begin
42
+
43
+ # Déterminer le type d'objet et créer l'adaptateur approprié
44
+ if obj.is_a?(::Doc)
45
+ # Document Core -> CMIS Document
46
+ adapter = CmisServer::DocumentAdapter.new(nil, context: @context)
47
+ cmis_doc = adapter.find(obj.id.to_s)
48
+ cmis_doc.to_renderable_object
49
+ elsif obj.is_a?(::Tagset) || (obj.respond_to?(:is_space) && obj.is_space)
50
+ # Tagset/Space Core -> CMIS Folder
51
+ adapter = CmisServer::FolderAdapter.new(nil, context: @context)
52
+ cmis_folder = adapter.find(obj.id.to_s)
53
+ cmis_folder.to_renderable_object
54
+ else
55
+ # Fallback: créer un document CMIS générique
56
+ doc_type = CmisServer::TypeRegistry.get_type('cmis:document') || CmisServer::DocumentType.base
57
+ properties = {
58
+ 'cmis:objectId' => CmisServer::Property.new(id: 'cmis:objectId', value: obj.id.to_s),
59
+ 'cmis:name' => CmisServer::Property.new(id: 'cmis:name', value: obj.respond_to?(:title) ? obj.title : 'Unknown')
60
+ }
61
+ cmis_doc = CmisServer::DocumentObject.new(type: doc_type, properties: properties)
62
+ cmis_doc.cmis_object_id = obj.id.to_s
63
+ cmis_doc.to_renderable_object
64
+ end
65
+ rescue => e
66
+ Rails.logger.error "NavigationService: Error converting object: #{e.message}"
67
+ Rails.logger.error "NavigationService: Backtrace: #{e.backtrace.first(5).join("\n")}"
68
+ raise e
69
+ end
70
+ end
12
71
 
13
72
  {
14
- objects: folder.adapter(context: @context).children(depth=1, limit: max_items, offset: skip_count, order_by: order_by).map { |o| o.to_renderable_object },
15
- has_more_items: true,
73
+ objects: renderable_objects,
74
+ has_more_items: children.count == max_items,
16
75
  }
17
76
  end
18
77
 
@@ -16,11 +16,23 @@ module CmisServer
16
16
  end
17
17
 
18
18
  def create_document(properties, folder_id: nil, content_stream: nil, versionning_state: :none, policies: [], add_aces: [], remove_aces: [])
19
- doc =CmisServer::DocumentObject.new(type: DocumentType.base, properties: properties)
19
+ # Utiliser le connecteur pour créer le document
20
+ connector = CmisServer::Connectors::ConnectorFactory.create_connector(
21
+ user: @context[:current_user] || @context.current_user
22
+ )
23
+
24
+ # Si le connecteur supporte la création directe
25
+ if connector.respond_to?(:create_document)
26
+ return connector.create_document(properties, folder_id: folder_id, content_stream: content_stream)
27
+ end
28
+
29
+ # Sinon, utiliser l'ancien système d'adapters
30
+ doc =CmisServer::DocumentObject.new(type: CmisServer::DocumentType.base, properties: properties)
20
31
  adapter=CmisServer::DocumentAdapter.new(doc, context: @context)
21
32
 
22
- if folder_id&&folder=CmisServer::FolderAdapter.class_adapter(context: @context).find(folder_id)
23
- adapter.add_to_folder(folder)
33
+ if folder_id
34
+ folder_adapter = CmisServer::FolderAdapter.class_adapter(context: @context).find(folder_id)
35
+ adapter.add_to_folder(folder_adapter)
24
36
  end
25
37
 
26
38
  if content_stream
@@ -35,8 +47,23 @@ module CmisServer
35
47
  raise NotImplemented
36
48
  end
37
49
 
38
- def create_folder(properties, add_aces: [], remove_aces: [])
39
- raise NotImplemented
50
+ def create_folder(properties, parent_folder_id: nil, add_aces: [], remove_aces: [])
51
+ # Utiliser le connecteur pour créer le dossier
52
+ connector = CmisServer::Connectors::ConnectorFactory.create_connector(
53
+ user: @context[:current_user] || @context.current_user
54
+ )
55
+
56
+ # Si le connecteur supporte la création directe
57
+ if connector.respond_to?(:create_folder)
58
+ return connector.create_folder(properties, parent_folder_id: parent_folder_id)
59
+ end
60
+
61
+ # Sinon, utiliser l'ancien système d'adapters
62
+ folder = CmisServer::FolderObject.new(type: CmisServer::TypeRegistry.get_type('cmis:folder'), properties: properties)
63
+ adapter = CmisServer::FolderAdapter.new(folder, context: @context)
64
+
65
+ adapter.save!
66
+ adapter.object.cmis_object_id
40
67
  end
41
68
 
42
69
  def create_relationship
@@ -48,7 +75,7 @@ module CmisServer
48
75
  end
49
76
 
50
77
  def create_item(properties, folder_id: nil, policies: [], add_aces: [], remove_aces: [])
51
- item = CmisServer::ItemObject.new(type: ItemType.base, properties: properties)
78
+ item = CmisServer::ItemObject.new(type: CmisServer::ItemType.base, properties: properties)
52
79
  adapter = CmisServer::ItemAdapter.new(item, context: @context)
53
80
 
54
81
  if folder_id && folder = CmisServer::FolderAdapter.class_adapter(context: @context).find(folder_id)
@@ -72,9 +99,39 @@ module CmisServer
72
99
  record = connector.find_object_by_id(id)
73
100
  raise CmisServer::ObjectNotFound unless record
74
101
 
75
- # Pour l'instant, retourner l'objet tel quel
76
- # TODO: implémenter la conversion en renderable_object
77
- record
102
+ # Convertir l'objet Core en objet CMIS avec RenderableObject
103
+ if record.is_a?(::Doc)
104
+ adapter = CmisServer::DocumentAdapter.new(nil, context: @context)
105
+ cmis_obj = adapter.find(record.id.to_s)
106
+ cmis_obj.to_renderable_object
107
+ elsif record.is_a?(::Tagset) || (record.respond_to?(:is_space) && record.is_space)
108
+ adapter = CmisServer::FolderAdapter.new(nil, context: @context)
109
+ cmis_obj = adapter.find(record.id.to_s)
110
+ cmis_obj.to_renderable_object
111
+ else
112
+ # Pour les objets déjà CMIS (comme root folder OpenStruct), créer un RenderableObject
113
+ # directement à partir de l'objet
114
+ if record.respond_to?(:to_renderable_object)
115
+ record.to_renderable_object
116
+ else
117
+ # Fallback : créer un folder CMIS basique
118
+ folder_type = CmisServer::TypeRegistry.get_type('cmis:folder') || CmisServer::FolderType.base
119
+ properties = {
120
+ 'cmis:objectId' => CmisServer::Property.new(id: 'cmis:objectId', value: record.id.to_s),
121
+ 'cmis:name' => CmisServer::Property.new(id: 'cmis:name', value: record.respond_to?(:title) ? record.title : record.respond_to?(:name) ? record.name : 'Unknown'),
122
+ 'cmis:baseTypeId' => CmisServer::Property.new(id: 'cmis:baseTypeId', value: 'cmis:folder'),
123
+ 'cmis:objectTypeId' => CmisServer::Property.new(id: 'cmis:objectTypeId', value: 'cmis:folder'),
124
+ 'cmis:createdBy' => CmisServer::Property.new(id: 'cmis:createdBy', value: record.respond_to?(:responsible) ? record.responsible : 'System'),
125
+ 'cmis:creationDate' => CmisServer::Property.new(id: 'cmis:creationDate', value: record.respond_to?(:created_at) ? record.created_at : Time.now),
126
+ 'cmis:lastModifiedBy' => CmisServer::Property.new(id: 'cmis:lastModifiedBy', value: record.respond_to?(:responsible) ? record.responsible : 'System'),
127
+ 'cmis:lastModificationDate' => CmisServer::Property.new(id: 'cmis:lastModificationDate', value: record.respond_to?(:updated_at) ? record.updated_at : Time.now),
128
+ 'cmis:parentId' => CmisServer::Property.new(id: 'cmis:parentId', value: nil)
129
+ }
130
+ folder = CmisServer::FolderObject.new(type: folder_type, properties: properties)
131
+ folder.cmis_object_id = record.id.to_s
132
+ folder.to_renderable_object
133
+ end
134
+ end
78
135
  end
79
136
 
80
137
  def get_properties(id, filter: [])
@@ -90,9 +147,39 @@ module CmisServer
90
147
  record = connector.find_object_by_path(path)
91
148
  raise CmisServer::ObjectNotFound unless record
92
149
 
93
- # Pour l'instant, retourner l'objet tel quel
94
- # TODO: implémenter la conversion en renderable_object
95
- record
150
+ # Utiliser la même logique que get_object pour convertir en RenderableObject
151
+ if record.is_a?(::Doc)
152
+ adapter = CmisServer::DocumentAdapter.new(nil, context: @context)
153
+ cmis_obj = adapter.find(record.id.to_s)
154
+ cmis_obj.to_renderable_object
155
+ elsif record.is_a?(::Tagset) || (record.respond_to?(:is_space) && record.is_space)
156
+ adapter = CmisServer::FolderAdapter.new(nil, context: @context)
157
+ cmis_obj = adapter.find(record.id.to_s)
158
+ cmis_obj.to_renderable_object
159
+ else
160
+ # Pour les objets déjà CMIS (comme root folder OpenStruct), créer un RenderableObject
161
+ if record.respond_to?(:to_renderable_object)
162
+ record.to_renderable_object
163
+ else
164
+ # Fallback : créer un folder CMIS basique
165
+ folder_type = CmisServer::TypeRegistry.get_type('cmis:folder') || CmisServer::FolderType.base
166
+ properties = {
167
+ 'cmis:objectId' => CmisServer::Property.new(id: 'cmis:objectId', value: record.id.to_s),
168
+ 'cmis:name' => CmisServer::Property.new(id: 'cmis:name', value: record.respond_to?(:title) ? record.title : record.respond_to?(:name) ? record.name : 'Unknown'),
169
+ 'cmis:path' => CmisServer::Property.new(id: 'cmis:path', value: path),
170
+ 'cmis:baseTypeId' => CmisServer::Property.new(id: 'cmis:baseTypeId', value: 'cmis:folder'),
171
+ 'cmis:objectTypeId' => CmisServer::Property.new(id: 'cmis:objectTypeId', value: 'cmis:folder'),
172
+ 'cmis:createdBy' => CmisServer::Property.new(id: 'cmis:createdBy', value: record.respond_to?(:responsible) ? record.responsible : 'System'),
173
+ 'cmis:creationDate' => CmisServer::Property.new(id: 'cmis:creationDate', value: record.respond_to?(:created_at) ? record.created_at : Time.now),
174
+ 'cmis:lastModifiedBy' => CmisServer::Property.new(id: 'cmis:lastModifiedBy', value: record.respond_to?(:responsible) ? record.responsible : 'System'),
175
+ 'cmis:lastModificationDate' => CmisServer::Property.new(id: 'cmis:lastModificationDate', value: record.respond_to?(:updated_at) ? record.updated_at : Time.now),
176
+ 'cmis:parentId' => CmisServer::Property.new(id: 'cmis:parentId', value: nil)
177
+ }
178
+ folder = CmisServer::FolderObject.new(type: folder_type, properties: properties)
179
+ folder.cmis_object_id = record.id.to_s
180
+ folder.to_renderable_object
181
+ end
182
+ end
96
183
  end
97
184
 
98
185
  def get_content_stream
@@ -156,7 +243,19 @@ module CmisServer
156
243
  raise NotImplemented
157
244
  end
158
245
 
159
- def delete_object
246
+ def delete_object(id, all_versions: true)
247
+ # Utiliser le connecteur pour supprimer l'objet
248
+ connector = CmisServer::Connectors::ConnectorFactory.create_connector(
249
+ user: @context[:current_user] || @context.current_user
250
+ )
251
+
252
+ # Si le connecteur supporte la suppression directe
253
+ if connector.respond_to?(:delete_object)
254
+ connector.delete_object(id)
255
+ return
256
+ end
257
+
258
+ # Sinon, utiliser l'ancien système
160
259
  raise NotImplemented
161
260
  end
162
261
 
@@ -1,3 +1,3 @@
1
1
  xml.link(rel: 'down',
2
- href: url_for(controller: 'cmis_server/atom_pub/folder_collection', action: 'get_children', id: object.cmis_object_id, only_path: false),
2
+ href: url_for(controller: 'cmis_server/atom_pub/folder_collection', action: 'get_children', id: object.respond_to?(:cmis_object_id) ? object.cmis_object_id : object.base_object.cmis_object_id, only_path: false),
3
3
  type: "application/atomsvc+xml")
@@ -15,8 +15,8 @@ xml.tag!('entry', 'xmlns:atom' => 'http://www.w3.org/2005/Atom',
15
15
  xml.content type: cs.media_type.to_s, src: url_for(controller: 'cmis_server/atom_pub/content', action: 'show', id: cs.id, only_path: false)
16
16
  end
17
17
  xml.link(rel: 'service', href: url_for(controller: 'cmis_server/atom_pub/service_documents', action: 'service_document', only_path: false), type: 'application/atomsvc+xml')
18
- xml.link(rel: 'self', href: url_for(controller: 'cmis_server/atom_pub/entries', action: 'show', id: object.base_object.cmis_object_id, only_path: false), type: 'application/atomsvc+xml')
19
- xml<<links_for(object.base_object)
18
+ xml.link(rel: 'self', href: url_for(controller: 'cmis_server/atom_pub/entries', action: 'show', id: object.respond_to?(:cmis_object_id) ? object.cmis_object_id : object.base_object.cmis_object_id, only_path: false), type: 'application/atomsvc+xml')
19
+ xml<<links_for(object.respond_to?(:type) ? object : object.base_object)
20
20
 
21
21
 
22
22
  # Non-AtomPub elements must be put at the end to validate XSD schema
@@ -57,7 +57,8 @@ xml.tag!('entry', 'xmlns:atom' => 'http://www.w3.org/2005/Atom',
57
57
  end
58
58
 
59
59
  if try(:with_path_segment)
60
- xml.tag!('cmisra:pathSegment', object.base_object.path_segment)
60
+ path_segment_object = object.respond_to?(:path_segment) ? object : object.base_object
61
+ xml.tag!('cmisra:pathSegment', path_segment_object.path_segment)
61
62
  end
62
63
 
63
64
  end
@@ -12,7 +12,7 @@ xml.tag!('entry', 'xmlns:atom' => 'http://www.w3.org/2005/Atom',
12
12
  xml.name 'unknown'
13
13
  end
14
14
 
15
- xml.link(rel: 'service', href: atom_pub_url, type: 'application/atomsvc+xml')
15
+ xml.link(rel: 'service', href: url_for(controller: 'cmis_server/atom_pub/service_documents', action: 'service_document', only_path: false), type: 'application/atomsvc+xml')
16
16
  xml.link(rel: 'self', href: url_for(controller: 'cmis_server/atom_pub/uri_templates', action: 'type_by_id', id: @type.id, only_path: false), type: 'application/atomsvc+xml')
17
17
 
18
18
  xml.tag!("app:edited", DateTime.now)
@@ -16,6 +16,9 @@ xml.tag!('atom:feed', 'xmlns:atom' => 'http://www.w3.org/2005/Atom',
16
16
  title: "Folder Collection",
17
17
  accept: "application/cmisatom+xml",
18
18
  })
19
+ else
20
+ # Pour le root folder virtuel, pas de collection link
21
+ # Car il n'a pas de parent
19
22
  end
20
23
 
21
24
  if @collection.total_items_count