source: trunk/LATMOS-Accounts-Web/lib/LATMOS/Accounts/Web/Model/AttrForms.pm @ 1064

Last change on this file since 1064 was 1064, checked in by nanardon, 12 years ago

Add puppet zones

This patch create a new zone type "puppet" which generate manifest files for a
set of computers.

Puppet class can be set in the zone or in the host, both settings are merged.

File size: 17.2 KB
Line 
1package LATMOS::Accounts::Web::Model::AttrForms;
2
3use strict;
4use warnings;
5use base 'Catalyst::Model';
6use LATMOS::Accounts::Log;
7use HTML::Prototype;
8
9=head1 NAME
10
11LATMOS::Accounts::Web::Model::AttrForms - Catalyst Model
12
13=head1 DESCRIPTION
14
15Catalyst Model.
16
17=cut
18
19my $forms = {
20    usersys => {
21        name => 'SystÚme',
22        attrs => [ qw(
23            sn givenName description
24            uid uidNumber gidNumber gecos homeDirectory loginShell
25            mail initials nickname
26            expire
27            locked
28            create
29            date
30        ) ],
31    },
32    user => {
33        name => 'Statut',
34        attrs => [ qw(
35            sn givenName description
36            company
37            department
38            manager
39            managerContact
40            contratType
41            expire
42            snNative
43            givenNameNative
44            wWWHomePage
45            halReference
46            create
47            date
48        ) ],
49    },
50    useraddress => {
51        name => 'Adresse',
52        attrs => [ qw(
53            initials
54            mail
55        ) ],
56    },
57    usermy => {
58        name => 'My',
59        attrs => [ qw(
60            snNative
61            givenNameNative
62            wWWHomePage
63            halReference
64        ) ],
65    },
66    site => {
67        name => 'Site',
68        attrs => [ qw(
69            description
70            siteNick
71            streetAddress
72            postOfficeBox
73            postalCode
74            l
75            st
76            co
77            facsimileTelephoneNumber
78            create
79            date
80        ) ],
81    },
82    address => {
83        name => 'Adresse',
84        attrs => [ qw(
85            isMainAddress
86            telephoneNumber
87            streetAddress
88            postOfficeBox
89            postalCode
90            l
91            st
92            physicalDeliveryOfficeName
93            site
94            co
95            unexported
96            description
97        ) ],
98    },
99    group => {
100        name => 'SystÚme',
101        attrs => [ qw(
102            gidNumber description
103            managedBy
104            sutype
105            create
106            date
107        ) ],
108    },
109    nethost => {
110        name => 'Ordinateur',
111        attrs => [ qw(
112            name
113            description
114            serialNumber
115            owner
116            user
117            ip
118            macaddr
119            puppetClass
120            noDynamic
121            cname
122            otherName
123            reverse
124            create
125            date
126            unexported
127        ) ],
128    },
129    netzone => {
130        name => 'Zone réseau',
131        attrs => [ qw(
132            name
133            description
134            type
135            net
136            netExclude
137            puppetClass
138            outputD
139            templateD
140            site
141            allow_dyn
142            dynFrom
143            domain
144            ipCount
145            freeIPCount
146            create
147            date
148            dnsRevision
149            lastUpdate
150            unexported
151        ) ],
152    },
153    aliases => {
154        name => 'Alias mail',
155        attrs => [ qw(
156            forward
157            expire
158            finalpoint
159            parents
160            created
161            date
162            unexported
163        )],
164    },
165};
166
167sub escape {
168    my ($self, $text) = @_;
169    $text ||= '';
170    for ($text) {
171        s/&/&/g;
172        s/</&lt;/g;
173        s/>/&gt;/g;
174        s/"/&quot;/g;
175    }
176    $text;
177}
178
179sub new {
180    my ($class) = @_;
181    bless({}, $class);
182}
183
184# call either OBJ or type + base
185
186sub ACCEPT_CONTEXT {
187    my ($self, $c, $form, $object, $base) = @_;
188    my $new = {};
189    $new->{c} = $c;
190    $new->{form} = $form;
191    $new->{object} = $object if (ref $object);
192    $new->{base} = $base || ($object ? $object->base : undef) or return $self;
193    $new->{otype} = ref $object ? $object->type : $object;
194    bless($new, __PACKAGE__);
195}
196
197sub base {
198    my ( $self ) = @_;
199    $self->{base}
200}
201
202sub otype {
203    my ($self) = @_;
204    $self->{otype};
205}
206
207sub label {
208    my ($self) = @_;
209    $forms->{$self->{form}}->{name} || ''
210}
211
212sub attributes {
213    my ($self, $for) = @_;
214    grep { $_ }
215    grep { $self->base->attribute($self->otype, $_) }
216    @{ $forms->{$self->{form}}->{attrs} };
217}
218
219sub attr_label {
220    my ($self, $attr, $label, $hint) = @_;
221    $label ||= '';
222    $hint ||= '';
223    LATMOS::Accounts::Web->config->{attrs} ||= {};
224    my $attribute = $self->base->attribute($self->otype, $attr);
225    my $htmlname = $self->escape($self->attr_field_name($attr));
226    if (my $attr_config = LATMOS::Accounts::Web->config->{attrs}{$attr}) {
227        $label ||= $attr_config->{label} || '';
228        #utf8::is_utf8($label) && utf8::encode($label);
229        $hint ||= $attr_config->{hint} || '';
230        #utf8::is_utf8($hint) && utf8::encode($hint);
231    }
232    return sprintf('<label %sfor="%s">%s</label>',
233        ($hint ? sprintf('title="%s"', $self->escape($hint)) : ''),
234        $self->escape($htmlname),
235        $self->escape($label || $attr),
236    );
237}
238
239sub attr_hint {
240    my ($self, $attr) = @_;
241    LATMOS::Accounts::Web->config->{attrs} ||= {};
242    if (my $attr_config = LATMOS::Accounts::Web->config->{attrs}{$attr}) {
243        return $attr_config->{hint} || '';
244    }
245    return;
246}
247
248sub attr_raw_value {
249    my ($self, $attribute) = @_;
250    my @val = grep { $_ } 
251        ($self->{c}->req->param($attribute->name))
252        || ($self->{object}
253            ? ($self->{object}->get_attributes($attribute->name))
254            : ());
255
256    if (@val) {
257        return @val;
258    } else {
259        return (grep { $_ } ($attribute->default_value))
260    }
261}
262
263sub attr_field_name {
264    my ($self, $attr) = @_;
265    my $id = $self->{object}
266        ? ($self->{object}->id || '')
267        : '';
268    $id .= '_' if ($id);
269    $id =~ s/\./_/g;
270    $id =~ s/-/_/g;
271    $id . $attr;
272}
273
274sub attr_item {
275    my ($self, $attribute, $value, $htmlid) = @_;
276
277    my $html = $self->_attr_item($attribute, $value, $htmlid);
278   
279    if ($attribute->uniq) {
280        $html .= qq|<span class="inputvalidate" id="${htmlid}_uniq"></span>|;
281    }
282    if (my $ref = $attribute->reference) {
283        my $uri_part = $self->_uri_part($ref);
284        if ($self->base->attribute($ref, 'displayName')) {
285            my $text = '';
286            if ($value &&
287                (my $obj = $self->base->get_object($ref, $value))) {
288                $text = $obj->get_attributes('displayName');
289            }
290            $html .= sprintf(
291                qq|<span id="${htmlid}_ref" style="margin-left: 1em">$text</span>|,
292                $self->escape($text),
293            );
294        } elsif($value && $uri_part) {
295            $html .= sprintf(
296                '<a href="%s"><img class="attr" src="%s" title="%s"></a>',
297                $self->{c}->uri_for('/', $uri_part, $value),
298                $self->{c}->uri_for('/static', 'icons', 'arrow-right.png'),
299                $value,
300            );
301        }
302    }
303
304    $html
305}
306
307sub _attr_item {
308    my ($self, $attribute, $value, $htmlid) = @_;
309
310    my $htmlname = $self->escape($self->attr_field_name($attribute->name));
311    $htmlid ||= $htmlname;
312
313    for ($attribute->form_type) {
314            /^textarea$/i and do {
315                return sprintf(
316                    '<textarea id="%s" name="%s" cols="40">%s</textarea>',
317                    $self->escape($htmlid),
318                    $self->escape($htmlname),
319                    $self->escape($value || ''),
320                );
321                last;
322            };
323
324            /^label$/i and do {
325                $value or last;
326                my $html_field = $self->escape($value);
327                $html_field =~ s/\n/<br>/g;
328                $html_field .= sprintf('<input type="hidden" name="%s" value="%s">',
329                    $self->escape($htmlname), ($value || ''));
330                return $html_field;
331                last;
332            };
333
334            /^date$/i and do {
335                my ($date, $time) = split(/ /, $value || '');
336                if ($date && $date =~ /^(\d+)-(\d+)-(\d+)$/) {
337                    $date = "$3/$2/$1";
338                }
339                my $html = "\n" . q{<SCRIPT LANGUAGE="JavaScript" ID="js13">
340                var cal13 = new CalendarPopup();
341                </SCRIPT>} . "\n";
342                $html .= sprintf(
343                    '<input type="text" id="%s" name="%s" value="%s" size="12">',
344                    $self->escape($htmlid),
345                    $self->escape($htmlname),
346                    $self->escape($date)
347                );
348                $html .= q{<DIV ID="testdiv1" STYLE="position:absolute;visibility:hidden;background-color:white;layer-background-color:white;"></DIV>};
349                $html .= qq|
350                <A HREF="#"
351                    onClick="cal13.select(document.getElementById('$htmlid'),'${htmlid}_anc','dd/MM/yyyy');return false;"
352                    TITLE="Date"
353                    NAME="${htmlid}_anc" ID="${htmlid}_anc">
354                    <img class="attr" src="| . $self->{c}->uri_for(qw(/static icons view-calendar-day.png))
355                    . qq{" style="ref"></A>
356                    } . "\n";
357                return $html;
358                last;
359            };
360
361            /^checkbox/i and do {
362                my $options = $1 || '';
363                my $html = sprintf('<input type="checkbox" id="%s" name="%s"%s>',
364                    $htmlid,
365                    $self->escape($htmlname),
366                    $value ? '  checked="yes"' : ''
367                ); 
368                $html .= sprintf('<input type="hidden" name="%s">',
369                    $self->escape($htmlname));
370                if ($attribute->form_option('rawvalue')) {
371                    $html .= $value
372                        ? ' ' . $value
373                        : ''; 
374                }
375                return $html;
376                last;
377            };
378
379            /^LIST/i and do {
380                my $select = sprintf('<select id="%s" name="%s">',
381                    $self->escape($htmlid),
382                    $self->escape($htmlname)) . "\n";
383                $select .= '<option value="">--</option>' . "\n"
384                    unless($attribute->mandatory);
385                $value ||= '';
386                my $initial_observed = '';
387                my @valslist;
388                foreach my $val (sort $attribute->can_values) {
389                    push(@valslist, {
390                        val => $val,
391                        disp => $attribute->display($val || ''),
392                    });
393                }
394                foreach (sort { $a->{disp} cmp $b->{disp} } @valslist) {
395                    $select .= sprintf(
396                        '    <option value="%s"%s>%s</option>',
397                        $self->escape($_->{val} || ''),
398                        $value eq $_->{val} ? ' selected="selected"' : '',
399                        $self->escape($_->{disp} || ''),
400                    );
401                    $select .= "\n";
402                }
403                $select .= "</select>\n";
404
405                return $select;
406                last;
407            };
408
409            /^text/i and do {
410                return sprintf(
411                    '<input type="text" id="%s" name="%s" value="%s" size="%d">',
412                    $self->escape($htmlid),
413                    $self->escape($htmlname),
414                    $self->escape($value),
415                    $attribute->form_option('length') || 30,
416                );
417                last;
418            };
419        }
420    return '';
421}
422
423sub _uri_part {
424    my ($self, $ref) = @_;
425    my $uri_part = {
426        user => 'users',
427        group => 'groups',
428        nethost => 'nethosts',
429        netzone => 'netzones',
430        site => 'sites'
431    }->{$ref};
432}
433
434sub attr_js {
435    my ($self, $attribute, $value, $htmlid) = @_;
436
437    my (@js);
438
439    if (my $ref = $attribute->reference) {
440        my $uri_part = $self->_uri_part($ref);
441        if ($self->base->attribute($ref, 'displayName')) {
442            push(@js, 
443                $self->{c}->prototype->observe_field( $htmlid,
444                    {
445                        update => "${htmlid}_ref",
446                        url => $self->{c}->uri_for('/ajax', 'rawattr', $ref),
447                        frequency => 1,
448                        with   => "'attr=displayName&id=' + element.options[element.selectedIndex].text",
449                    }
450                )
451            ) if ($attribute->form_type =~ /list/i);
452        }
453    }
454
455    if ($attribute->uniq) {
456        push(@js,
457            $self->{c}->prototype->observe_field( $htmlid,
458                {
459                    update => "${htmlid}_uniq",
460                    url => $self->{c}->uri_for('/ajax', 'objattrexist',
461                        $self->otype, $attribute->name),
462                    frequency => 1,
463                    with => "'val='+element.value" .
464                    ($self->{object} ?
465                        "+'&exclude=" . ($self->{object}->id || '') . "'" 
466                        : ''),
467                }
468            )
469        );
470    }
471
472    return(join("\n", @js));
473}
474
475sub attr_field {
476    my ($self, $attr, $type) = @_;
477
478    my $attribute;
479    if ($type) {
480        if (ref $type) {
481            $attribute = $self->base->attribute(
482                $self->otype,
483                { %$type, name => $attr },
484            );
485        } else {
486            $attribute =  $self->base->attribute(
487                $self->otype,
488                { formtype => $type , name => $attr },
489            );
490        }
491    } else {
492        if ($self->{object}) {
493            $attribute = $self->{object}->attribute($attr);
494        } else {
495            $attribute = $self->base->attribute(
496                $self->otype, $attr,
497                { formtype => $type }
498            );
499        }
500    }
501    $attribute ||= $self->base->attribute($self->otype, { name => $attr });
502
503
504    my $htmlname = $self->escape($self->attr_field_name($attr));
505
506    my @html_fields;
507
508    # Force Array context:
509    my @attr_raw_value = ();
510
511    if ($attribute->multiple) {
512        @attr_raw_value = grep { $_ } $self->attr_raw_value($attribute);
513    } else {
514        my ($val) = $self->attr_raw_value($attribute);
515        @attr_raw_value = ($val || '');
516    }
517
518    foreach my $attr_raw_value (@attr_raw_value) {
519
520        my $html_id = $htmlname .
521            (scalar(@html_fields) ? scalar(@html_fields) : '');
522        push(@html_fields,
523            join("\n",
524                $self->attr_item(
525                    $attribute, $attr_raw_value, $html_id
526                ),
527                $self->attr_js(
528                    $attribute, $attr_raw_value, $html_id
529                )
530            )
531        );
532    }
533
534    if ($attribute->{multiple} && !$attribute->readonly) {
535        my $html_id = $htmlname . '_m_SUBID';
536
537        my $attr = $self->attr_item($attribute, '', $html_id);
538        # JS: string are on the line only
539        $attr =~ s/\n//mg;
540        $attr =~ s/'/\'/g;
541
542        my $js = $self->attr_js($attribute, '', 'NANAR');
543        $js =~ s!'NANAR([_\w]*)'!('$html_id$1'.replace(/SUBID/g, cn))!gm;
544        $js =~ s!<script[^>]+>!!gm;
545        $js =~ s!</script>!!gm;
546        $js =~ s!-->!!gm;
547        $js =~ s/<!--//gm;
548
549        my $addempty = sprintf('<div id="%s"></div>', "${htmlname}_div_0");
550        $addempty .= "\n";
551        $addempty .= sprintf(qq#
552            <script type="text/javascript">
553            var cn_${htmlname} = 0;
554            function add_${htmlname} () {
555            cn_${htmlname}++;
556            // It work only using temporary variable
557            var cn = cn_${htmlname};
558            document.getElementById('${htmlname}_div_' + (cn - 1)).innerHTML +=
559                '$attr'.replace(/SUBID/g, cn );
560            document.getElementById('${htmlname}_div_' + (cn - 1)).innerHTML +=
561                '<div id="${htmlname}_div_'+ cn +'"></div>';
562            %s
563            }
564            </script>
565            #, $js
566        );
567
568        $addempty .= "\n";
569        $addempty .=
570            qq|<button type="button" onclick="add_${htmlname}()">+</button>|,
571
572        push(@html_fields, $addempty);
573    }
574
575    return join("<br>\n", @html_fields);
576}
577
578sub submit {
579    my ($self) = @_;
580    return sprintf(
581        '<input type="submit" name="%s" value="Enregistrer">',
582        $self->escape($self->label),
583    );
584}
585
586sub write_attributes {
587    my ($self) = @_;
588    my @attrs;
589    foreach ($self->attributes) {
590        my $attr = ($self->{object}
591            ? $self->{object}->attribute($_)
592            : $self->base->attribute($self->otype, $_)) or next;
593        $attr->readonly and next;
594        push(@attrs, $_);
595    }
596    @attrs;
597}
598
599sub set_attrs {
600    my ($self, $attrs) = @_;
601    $self->{c}->req->param($self->label) || $attrs or return;
602    my $prefix = $self->attr_field_name('');
603    my %fields;
604    foreach ($attrs ? @{ $attrs } : $self->write_attributes) {
605        my $attr = ($self->{object}
606            ? $self->{object}->attribute($_)
607            : $self->base->attribute($self->otype, $_)) or next;
608        if ($attr->{multiple}) {
609            $fields{$_} = [ grep { $_ } $self->{c}->req->param("$prefix$_") ];
610        } else {
611            $fields{$_} = $self->{c}->req->param("$prefix$_");
612        }
613    }
614    $self->{object}->set_c_fields(%fields) or do {
615        $self->{c}->stash->{page}{error} =
616            LATMOS::Accounts::Log::lastmessage(LA_ERR);
617        $self->{object}->base->rollback;
618        return;
619    };
620    $self->{object}->base->commit;
621}
622
623=head1 AUTHOR
624
625Thauvin Olivier
626
627=head1 LICENSE
628
629This library is free software, you can redistribute it and/or modify
630it under the same terms as Perl itself.
631
632=cut
633
6341;
Note: See TracBrowser for help on using the repository browser.