MOON
Server: Apache
System: Linux server1.studioinfinity.com.br 2.6.32-954.3.5.lve1.4.90.el6.x86_64 #1 SMP Tue Feb 21 12:26:30 UTC 2023 x86_64
User: artinside (517)
PHP: 7.4.33
Disabled: exec,passthru,shell_exec,system
Upload Files
File: //usr/local/lib64/perl5/Cpanel/Class/Meta/Attribute.pm
package Cpanel::Class::Meta::Attribute;

use strict;

use warnings;
use Carp 'confess';
use Scalar::Util 'blessed', 'reftype', 'isweak', 'weaken';

use base 'Cpanel::Class::Meta::Class';

our $VERSION = '1.0.5';

sub new {
    my ( $class, $args ) = @_;

    confess "Argument to new must be hash reference" if reftype $args ne 'HASH';
    confess 'package is required argument'
      if !exists $args->{'package'} and !$args->{'package'};

    my $self = $class->SUPER::new($args);

    $self = {
        %{$self},
        '$!attr_name'        => $args->{'attr'},
        '$!reader'           => $args->{'reader'},
        '$!writer'           => $args->{'writer'},
        '$!default'          => $args->{'default'},
        '$!is'               => $args->{'is'},
        '$!handles'          => $args->{'handles'},
        '$!predicate'        => $args->{'predicate'},
        '$!init_arg'         => $args->{'init_arg'},
        '$!lazy'             => $args->{'lazy'},
        '$!weaken_ref'       => $args->{'weaken_ref'},
        '$!auto_deref'       => $args->{'auto_deref'},
        '$!trigger'          => $args->{'trigger'},
        '$!clearer'          => $args->{'clearer'},
        '$!builder'          => $args->{'builder'},
        '$!required'         => $args->{'required'},
        '$!associated_class' => '',
    };

    delete $self->{'%!attributes'};
    delete $self->{'$!attribute_metaclass'};
    delete $self->{'%!methods'};

    return bless $self, $class;
}

sub associated_class { $_[0]->{'$!associated_class'} }

sub attr {
    my ($self) = @_;
    return $self->{'$!attr_name'};
}

sub reader {
    my ($self) = @_;
    return $self->{'$!reader'};
}

sub writer {
    my ($self) = @_;
    return $self->{'$!writer'};
}

sub default {
    my ($self) = @_;
    return $self->{'$!default'};
}

sub is {
    my ($self) = @_;
    return $self->{'$!is'};
}

sub handles {
    my ($self) = @_;
    return $self->{'$!handles'};
}

sub predicate {
    my ($self) = @_;
    return $self->{'$!predicate'};
}

sub init_arg {
    my ($self) = @_;
    return $self->{'$!init_arg'};
}

sub lazy {
    my ($self) = @_;
    return $self->{'$!lazy'};
}

sub weaken_ref {
    my ($self) = @_;
    return $self->{'$!weaken_ref'};
}

sub auto_deref {
    my ($self) = @_;
    return $self->{'$!auto_deref'};
}

sub trigger {
    my ($self) = @_;
    return $self->{'$!trigger'};
}

sub clearer {
    my ($self) = @_;
    return $self->{'$!clearer'};
}

sub builder {
    my ($self) = @_;
    return $self->{'$!builder'};
}

sub required {
    my ($self) = @_;
    return $self->{'$!required'};
}

sub has_is        { defined( $_[0]->is )        ? 1 : 0 }
sub has_reader    { defined( $_[0]->reader )    ? 1 : 0 }
sub has_writer    { defined( $_[0]->writer )    ? 1 : 0 }
sub has_predicate { defined( $_[0]->predicate ) ? 1 : 0 }
sub has_init_arg  { defined( $_[0]->init_arg )  ? 1 : 0 }
sub has_default   { defined( $_[0]->default )   ? 1 : 0 }
sub has_handles   { defined( $_[0]->handles )   ? 1 : 0 }
sub has_trigger   { defined( $_[0]->trigger )   ? 1 : 0 }
sub has_clearer   { defined( $_[0]->clearer )   ? 1 : 0 }
sub has_builder   { defined( $_[0]->builder )   ? 1 : 0 }
sub is_lazy       { $_[0]->lazy }
sub is_weak       { $_[0]->weaken_ref }
sub is_auto_deref { $_[0]->auto_deref }
sub is_required   { $_[0]->required }

sub build_attribute {
    my ($self) = @_;

    confess 'triggers cannot be called on read-only(ro) attributes'
      if $self->has_trigger and $self->is eq 'ro';
    confess 'trigger must be a code ref'
      if $self->has_trigger and reftype $self->trigger ne 'CODE';
    confess 'Setting both default and builder is not allowed'
      if $self->has_default and $self->has_builder;
    confess 'builder must be a defined scalar value which is a method name'
      if $self->has_builder
          and ( ref $self->builder || !( defined( $self->builder ) ) );

    if ( $self->reader eq $self->writer ) {
        if ( $self->has_is and $self->is eq 'ro' ) {
            $self->_ro_method();
        }
        elsif ( $self->has_is and $self->is eq 'wo' ) {
            $self->_wo_method();
        }
        elsif ( $self->has_is and $self->is eq 'rw' ) {
            $self->_rw_method();
        }
    }
    else {
        if ( $self->has_is and $self->is eq 'ro' ) {
            $self->_ro_method();
        }
        elsif ( $self->has_is and $self->is eq 'wo' ) {
            $self->_wo_method();
        }
        elsif ( $self->has_is and $self->is eq 'rw' ) {
            $self->_ro_method();
            $self->_wo_method();
        }
    }

    if (
        $self->has_handles
        and (  reftype $self->handles eq 'HASH'
            or reftype $self->handles eq 'ARRAY' )
      ) {
        $self->build_handles();
    }

    if ( $self->has_predicate ) {
        $self->build_predicate();
    }

    if ( $self->has_clearer ) {
        $self->build_clearer();
    }

}

sub attach_to_class {
    my ( $self, $class ) = @_;
    weaken( $self->{'$!associated_class'} = $class );
}

sub build_clearer {
    my ($attribute) = @_;
    $attribute->associated_class->add_method(
        $attribute->clearer => sub {
            my ($self) = @_;
            delete $self->{ $attribute->attr };
        }
    );
}

sub build_handles {
    my ($attribute) = @_;
    if ( reftype $attribute->handles eq 'HASH' ) {
        $attribute->_handles_hash( $attribute->attr, $attribute->reader, $attribute->handles );
    }
    elsif ( reftype $attribute->handles eq 'ARRAY' ) {
        $attribute->_handles_array( $attribute->attr, $attribute->reader, $attribute->handles );
    }
}

sub build_predicate {
    my ($attribute) = @_;
    $attribute->associated_class->add_method(
        $attribute->predicate => sub {
            my ($self) = @_;

            if ( exists $self->{ $attribute->attr }
                and ref $self->{ $attribute->attr } ) {
                if ( ref $self->{ $attribute->attr } eq 'ARRAY' ) {
                    return ( @{ $self->{ $attribute->attr } } ) ? 1 : 0;
                }
                elsif ( ref $self->{ $attribute->attr } eq 'HASH' ) {
                    return ( %{ $self->{ $attribute->attr } } ) ? 1 : 0;
                }
                else {
                    return ( defined $self->{ $attribute->attr } ) ? 1 : 0;
                }
            }
            elsif ( exists $self->{ $attribute->attr } ) {
                return ( defined $self->{ $attribute->attr } ) ? 1 : 0;
            }
            else {
                return 0;
            }
        }
    );
}

# Private

sub _ro_method {
    my ($attribute) = @_;

    my %seen_default = ();

    $attribute->associated_class->add_method(
        $attribute->reader => sub {
            my ($self) = @_;
            confess $attribute->reader . ' is a read only accessor.'
              if scalar @_ > 1;

            my $id = $self + 0;

            if ( $attribute->builder ) {
                if ( my $build_method = $self->can( $attribute->builder ) ) {
                    $self->{ $attribute->attr } ||= $self->$build_method($self);
                }
            }

            if ( !exists $seen_default{$id} or !$self->{ $attribute->attr } ) {
                if ( !$seen_default{$id} ) {
                    $self->{ $attribute->attr } ||=
                      ( $attribute->default and ref $attribute->default eq 'CODE' )
                      ? $attribute->default->($self)
                      : $attribute->default;

                    $seen_default{$id} = 1;

                }
            }

            if (    $attribute->is_weak
                and $self->{ $attribute->attr }
                and !isweak( $self->{ $attribute->attr } ) ) {
                weaken( $self->{ $attribute->attr } );
            }

            if ( $attribute->is_required
                and !defined( $self->{ $attribute->attr } ) ) {
                my $name = $attribute->attr;
                confess "attribute \"$name\" is required to be set";
            }

            return _return_attr( $self, $attribute->attr, $attribute->is_auto_deref );
        }
    );
}

sub _rw_method {
    my ($attribute) = @_;

    my %seen_default = ();

    $attribute->associated_class->add_method(
        $attribute->writer => sub {
            my ( $self, $value ) = @_;

            my $id = $self + 0;

            if ( $attribute->builder ) {
                if ( my $build_method = $self->can( $attribute->builder ) ) {
                    $self->{ $attribute->attr } ||= $self->$build_method($self);
                }
            }

            if ( !exists $seen_default{$id} or !$value ) {
                if ( !$seen_default{$id} ) {
                    $self->{ $attribute->attr } ||=
                      ( $attribute->default and ref $attribute->default eq 'CODE' )
                      ? $attribute->default->($self)
                      : $attribute->default;

                    $seen_default{$id} = 1;
                }
            }

            $self->{ $attribute->attr } = $value if defined $value;
            if (    $attribute->is_weak
                and $self->{ $attribute->attr }
                and !isweak( $self->{ $attribute->attr } ) ) {
                weaken( $self->{ $attribute->attr } );
            }

            if (    $attribute->has_trigger
                and reftype $attribute->trigger eq 'CODE'
                and defined $value ) {
                $attribute->trigger->( $self, $self->{ $attribute->attr }, $attribute );
            }

            if ( $attribute->is_required
                and !defined( $self->{ $attribute->attr } ) ) {
                my $name = $attribute->attr;
                confess "attribute \"$name\" is required to be set";
            }

            return _return_attr( $self, $attribute->attr, $attribute->is_auto_deref );
        }
    );
}

sub _wo_method {
    my ($attribute) = @_;

    my %seen_default = ();

    $attribute->associated_class->add_method(
        $attribute->writer => sub {
            my ( $self, $value ) = @_;

            my $id = $self + 0;

            if ( $attribute->builder ) {
                if ( my $build_method = $self->can( $attribute->builder ) ) {
                    $self->{ $attribute->attr } ||= $self->$build_method($self);
                }
            }

            if ( !exists $seen_default{$id} or !$value ) {
                if ( !$seen_default{$id} ) {
                    $self->{ $attribute->attr } ||=
                      ( $attribute->default and ref $attribute->default eq 'CODE' )
                      ? $attribute->default->($self)
                      : $attribute->default;

                    $seen_default{$id} = 1;
                }
            }

            $self->{ $attribute->attr } = $value if defined $value;
            if (    $attribute->is_weak
                and $self->{ $attribute->attr }
                and !isweak( $self->{ $attribute->attr } ) ) {
                weaken( $self->{ $attribute->attr } );
            }

            if (    $attribute->has_trigger
                and reftype $attribute->trigger eq 'CODE'
                and defined $value ) {
                $attribute->trigger->( $self, $self->{ $attribute->attr }, $attribute );
            }

            if ( $attribute->is_required
                and !defined( $self->{ $attribute->attr } ) ) {
                my $name = $attribute->attr;
                confess "attribute \"$name\" is required to be set";
            }

            return _return_attr( $self, $attribute->attr, $attribute->is_auto_deref );
        }
    );
}

sub _handles_array {
    my ( $self, $attr, $reader, $handles ) = @_;

    foreach my $method ( @{$handles} ) {
        $self->associated_class->add_method(
            $method => sub {
                my ( $self, @args ) = @_;

                if ( $self->$reader->can($method) ) {
                    return $self->$reader->$method(@args);
                }
                else {
                    confess( 'Cannot call ' . $method . ' from ' . $reader );
                }
            }
        );
    }
}

sub _handles_hash {
    my ( $self, $attr, $reader, $handles ) = @_;

    foreach my $method ( keys %{$handles} ) {
        my $handle = $handles->{$method};
        $self->associated_class->add_method(
            $method => sub {
                my ( $self, @args ) = @_;

                if ( $self->$reader->can($handle) ) {
                    return $self->$reader->$handle(@args);
                }
                else {
                    croak( 'Cannot call ' . $handle . ' from ' . $reader );
                }
            }
        );
    }
}

sub _return_attr {
    my ( $self, $attr, $is_auto_deref ) = @_;

    if ( $is_auto_deref and defined $self->{$attr} ) {
        if ( reftype $self->{$attr} eq 'ARRAY' ) {
            return (wantarray) ? @{ $self->{$attr} } : $self->{$attr};
        }
        elsif ( reftype $self->{$attr} eq 'HASH' ) {
            return (wantarray) ? %{ $self->{$attr} } : $self->{$attr};
        }
        else {
            return $self->{$attr};
        }
    }
    else {
        return $self->{$attr};
    }
}

sub detach_from_class {
    my $self = shift;
    $self->{'$!associated_class'} = undef;
}

{
    my $_remove_accessor = sub {
        my ( $accessor, $class ) = @_;
        if ( reftype($accessor) && reftype($accessor) eq 'HASH' ) {
            ($accessor) = keys %{$accessor};
        }
        my $method = $class->get_method($accessor);
        $class->remove_method($accessor)
          if ( blessed($method) && $method->isa('Class::MOP::Method::Accessor') );
    };

    sub remove_accessors {
        my $self = shift;

        $_remove_accessor->( $self->reader(),    $self->associated_class() ) if $self->has_reader();
        $_remove_accessor->( $self->writer(),    $self->associated_class() ) if $self->has_writer();
        $_remove_accessor->( $self->predicate(), $self->associated_class() ) if $self->has_predicate();
        $_remove_accessor->( $self->clearer(),   $self->associated_class() ) if $self->has_clearer();
        return;
    }

}

1;