File Coverage

blib/lib/Couch/DB/Design.pm
Criterion Covered Total %
statement 21 74 28.3
branch 0 18 0.0
condition 0 3 0.0
subroutine 7 24 29.1
pod 14 15 93.3
total 42 134 31.3


line stmt bran cond sub pod time code
1             # This code is part of Perl distribution Couch-DB version 0.201.
2             # The POD got stripped from this file by OODoc version 3.06.
3             # For contributors see file ChangeLog.
4              
5             # This software is copyright (c) 2024-2026 by Mark Overmeer.
6              
7             # This is free software; you can redistribute it and/or modify it under
8             # the same terms as the Perl 5 programming language system itself.
9             # SPDX-License-Identifier: Artistic-1.0-Perl OR GPL-1.0-or-later
10              
11              
12             package Couch::DB::Design;{
13             our $VERSION = '0.201';
14             }
15              
16 1     1   1923 use parent 'Couch::DB::Document';
  1         2  
  1         12  
17              
18 1     1   102 use warnings;
  1         2  
  1         56  
19 1     1   7 use strict;
  1         2  
  1         30  
20              
21 1     1   6 use Couch::DB::Util;
  1         2  
  1         8  
22              
23 1     1   9 use Log::Report 'couch-db';
  1         2  
  1         30  
24              
25 1     1   327 use URI::Escape qw/uri_escape/;
  1         3  
  1         130  
26 1     1   9 use Scalar::Util qw/blessed/;
  1         2  
  1         2025  
27              
28             my $id_generator;
29              
30             #--------------------
31              
32             sub init($)
33 0     0 0   { my ($self, $args) = @_;
34 0   0       my $which = $args->{id} || $id_generator->($args->{db} or panic);
35 0 0         my ($id, $base) = $which =~ m!^_design/(.*)! ? ($which, $1) : ("_design/$which", $which);
36 0           $args->{id} = $id;
37              
38 0           $self->SUPER::init($args);
39 0           $self->{CDD_base} = $base;
40 0           $self;
41             }
42              
43             #--------------------
44              
45             $id_generator = sub ($) { $_[0]->couch->freshUUID };
46 0     0 1   sub setIdGenerator($) { $id_generator = $_[1] }
47              
48              
49 0     0 1   sub idBase() { $_[0]->{CDD_base} }
50              
51             #--------------------
52              
53             sub create($%)
54 0     0 1   { my $self = shift;
55 0           $self->update(@_);
56             }
57              
58              
59             sub update($%)
60 0     0 1   { my ($self, $data, %args) = @_;
61 0           $data->{_id} = $self->id;
62              
63             $self->couch
64             ->toJSON($data, bool => qw/autoupdate/)
65             ->check($data->{lists}, deprecated => '3.0.0', 'DesignDoc create() option list')
66             ->check($data->{lists}, removed => '4.0.0', 'DesignDoc create() option list')
67             ->check($data->{show}, deprecated => '3.0.0', 'DesignDoc create() option show')
68             ->check($data->{show}, removed => '4.0.0', 'DesignDoc create() option show')
69 0           ->check($data->{rewrites}, deprecated => '3.0.0', 'DesignDoc create() option rewrites');
70              
71             #XXX Do we need more parameter conversions in the nested queries?
72              
73 0           $self->SUPER::create($data, %args);
74             }
75              
76             # get/delete/etc. are simply produced by extension of the _pathToDoc() which
77             # adds "_design/" to the front of the path.
78              
79             sub details(%)
80 0     0 1   { my ($self, %args) = @_;
81              
82 0           $self->couch->call(GET => $self->_pathToDoc('_info'),
83             $self->couch->_resultsConfig(\%args),
84             );
85             }
86              
87             #--------------------
88              
89             #--------------------
90              
91             sub createIndex($%)
92 0     0 1   { my ($self, $config, %args) = @_;
93              
94 0           my $send = +{ %$config, ddoc => $self->id };
95 0           my $couch = $self->couch;
96 0           $couch->toJSON($send, bool => qw/partitioned/);
97              
98 0           $couch->call(POST => $self->db->_pathToDB('_index'),
99             send => $send,
100             $couch->_resultsConfig(\%args),
101             );
102             }
103              
104              
105             sub deleteIndex($%)
106 0     0 1   { my ($self, $ddoc, $index, %args) = @_;
107 0           my $id = $self->idBase; # id() would also work
108 0           $self->couch->call(DELETE => $self->db->_pathToDB("_index/$id/json/" . uri_escape($index)),
109             $self->couch->_resultsConfig(\%args),
110             );
111             }
112              
113              
114             sub __searchRow($$$%)
115 0     0     { my ($self, $result, $index, $column, %args) = @_;
116 0 0         my $answer = $result->answer->{rows}[$index] or return ();
117 0           my $values = $result->values->{rows}[$index];
118              
119             ( answer => $answer,
120             values => $values,
121 0 0         docdata => $args{full_docs} ? $values : undef,
122             docparams => { db => $self },
123             );
124             }
125              
126             sub search($$%)
127 0     0 1   { my ($self, $index, $search, %args) = @_;
128 0 0         my $query = defined $search ? +{ %$search } : {};
129              
130             # Everything into the query :-( Why no POST version?
131 0           my $couch = $self->couch;
132 0           $couch
133             ->toQuery($query, json => qw/counts drilldown group_sort highlight_fields include_fields ranges sort/)
134             ->toQuery($query, int => qw/highlight_number highlight_size limit/)
135             ->toQuery($query, bool => qw/include_docs/);
136              
137             $couch->call(GET => $self->_pathToDoc('_search/' . uri_escape $index),
138             introduced => '3.0.0',
139             query => $query,
140             $couch->_resultsPaging(\%args,
141 0     0     on_row => sub { $self->__searchRow(@_, full_docs => $search->{include_docs}) },
142 0           ),
143             );
144             }
145              
146              
147             sub indexDetails($%)
148 0     0 1   { my ($self, $index, %args) = @_;
149              
150 0           $self->couch->call(GET => $self->_pathToDoc('_search_info/' . uri_escape($index)),
151             introduced => '3.0.0',
152             $self->couch->_resultsConfig(\%args),
153             );
154             }
155              
156             #--------------------
157              
158             sub viewDocs($;$%)
159 0     0 1   { my ($self, $view, $search, %args) = @_;
160 0           $self->db->allDocs($search, view => $view, design => $self, %args);
161             }
162              
163              
164             sub compactViews(%)
165 0     0 1   { my ($self, %args) = @_;
166              
167 0           $self->couch->call(POST => $self->_pathToDB('_compact/', uri_escape($self->baseId)),
168             send => +{},
169             $self->couch->_resultsConfig(\%args),
170             );
171             }
172              
173             #--------------------
174              
175             sub show($;$%)
176 0     0 1   { my ($self, $function, $doc, %args) = @_;
177 0           my $path = $self->_pathToDoc('_show/'.uri_escape($function));
178 0 0         $path .= '/' . (blessed $doc ? $doc->id : $doc) if defined $doc;
    0          
179              
180 0           $self->couch->call(GET => $path,
181             deprecated => '3.0.0',
182             removed => '4.0.0',
183             $self->couch->_resultsConfig(\%args),
184             );
185             }
186              
187              
188             sub list($$%)
189 0     0 1   { my ($self, $function, $view, %args) = @_;
190              
191 0 0         my $other = defined $args{view_ddoc} ? '/'.delete $args{view_ddoc} : '';
192 0           my $path = $self->_pathToDoc('_list/' . uri_escape($function) . $other . '/' . uri_escape($view));
193              
194 0           $self->couch->call(GET => $path,
195             deprecated => '3.0.0',
196             removed => '4.0.0',
197             $self->couch->_resultsConfig(\%args),
198             );
199             }
200              
201              
202             #XXX The 3.3.3 doc says /{docid} version requires PUT, but shows a POST example.
203             #XXX The 3.3.3post4 docs make the example patch with PUT.
204             #XXX The code probably says: anything except GET is okay.
205              
206             sub applyUpdate($%)
207 0     0 1   { my ($self, $function, $doc, %args) = @_;
208 0           my $path = $self->_pathToDoc('_update/'.uri_escape($function));
209 0 0         $path .= '/' . (blessed $doc ? $doc->id : $doc) if defined $doc;
    0          
210              
211 0           $self->couch->call(POST => $path,
212             deprecated => '3.0.0',
213             removed => '4.0.0',
214             send => { },
215             $self->couch->_resultsConfig(\%args),
216             );
217             }
218              
219             # [CouchDB API "ANY /{db}/_design/{ddoc}/_rewrite/{path}", deprecated 3.0, removed 4.0, UNSUPPORTED]
220             # The documentation of this method is really bad, and you probably should do this in your programming
221             # language anyway.
222              
223             1;