| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package OpenInteract2::Manage; | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  | # $Id: Manage.pm,v 1.49 2005/03/17 14:57:58 sjn Exp $ | 
| 4 |  |  |  |  |  |  |  | 
| 5 | 1 |  |  | 1 |  | 16315 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 213 |  | 
| 6 | 1 |  |  | 1 |  | 7 | use base qw( Exporter OpenInteract2::ParamContainer Class::Factory Class::Observable ); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 1196 |  | 
| 7 |  |  |  |  |  |  | use Cwd                      qw( cwd ); | 
| 8 |  |  |  |  |  |  | use File::Spec::Functions    qw( :ALL ); | 
| 9 |  |  |  |  |  |  | use Log::Log4perl            qw( get_logger :levels ); | 
| 10 |  |  |  |  |  |  | use OpenInteract2::Constants qw( :log ); | 
| 11 |  |  |  |  |  |  | use OpenInteract2::Context   qw( CTX ); | 
| 12 |  |  |  |  |  |  | use OpenInteract2::Exception qw( oi_error oi_param_error ); | 
| 13 |  |  |  |  |  |  | use OpenInteract2::Setup; | 
| 14 |  |  |  |  |  |  |  | 
| 15 |  |  |  |  |  |  | $OpenInteract2::Manage::VERSION = sprintf("%d.%02d", q$Revision: 1.49 $ =~ /(\d+)\.(\d+)/); | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | my $SYSTEM_PACKAGES = [ | 
| 18 |  |  |  |  |  |  | qw/ base       base_box        base_error    base_group | 
| 19 |  |  |  |  |  |  | base_page  base_security   base_template base_theme | 
| 20 |  |  |  |  |  |  | base_user  comments        full_text     news | 
| 21 |  |  |  |  |  |  | lookup     object_activity system_doc    whats_new / | 
| 22 |  |  |  |  |  |  | ]; | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | sub SYSTEM_PACKAGES { return $SYSTEM_PACKAGES } | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | my %PACKAGE_GROUPS = ( | 
| 27 |  |  |  |  |  |  | SYSTEM => $SYSTEM_PACKAGES, | 
| 28 |  |  |  |  |  |  | ); | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | use constant DEV_LIST  => 'openinteract-dev@lists.sourceforge.net'; | 
| 31 |  |  |  |  |  |  | use constant HELP_LIST => 'openinteract-help@lists.sourceforge.net'; | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | @OpenInteract2::Manage::EXPORT_OK = qw( | 
| 34 |  |  |  |  |  |  | SYSTEM_PACKAGES DEV_LIST HELP_LIST | 
| 35 |  |  |  |  |  |  | ); | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | ######################################## | 
| 38 |  |  |  |  |  |  | # MAIN EXTERNAL INTERFACE | 
| 39 |  |  |  |  |  |  |  | 
| 40 |  |  |  |  |  |  | sub new { | 
| 41 |  |  |  |  |  |  | my ( $pkg, $task_name, $params, @extra ) = @_; | 
| 42 |  |  |  |  |  |  | my $class = $pkg->get_factory_class( $task_name ); | 
| 43 |  |  |  |  |  |  | my $self = bless( { _status => [] }, $class ); | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | if ( ref $params eq 'HASH' ) { | 
| 46 |  |  |  |  |  |  | while ( my ( $name, $value ) = each %{ $params } ) { | 
| 47 |  |  |  |  |  |  | $self->param( $name => $value ); | 
| 48 |  |  |  |  |  |  | } | 
| 49 |  |  |  |  |  |  | } | 
| 50 |  |  |  |  |  |  |  | 
| 51 |  |  |  |  |  |  | # Check for defaults | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | my $param_metadata = $self->get_parameters; | 
| 54 |  |  |  |  |  |  | foreach my $name ( keys %{ $param_metadata } ) { | 
| 55 |  |  |  |  |  |  | next if ( $self->param( $name ) ); | 
| 56 |  |  |  |  |  |  | next unless ( $param_metadata->{ $name }{default} ); | 
| 57 |  |  |  |  |  |  | $self->param( $name => $param_metadata->{ $name }{default} ); | 
| 58 |  |  |  |  |  |  | } | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | $self->init( @extra ); | 
| 61 |  |  |  |  |  |  | return $self; | 
| 62 |  |  |  |  |  |  | } | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | sub execute { | 
| 65 |  |  |  |  |  |  | my ( $self ) = @_; | 
| 66 |  |  |  |  |  |  | $self->check_parameters; | 
| 67 |  |  |  |  |  |  | $self->setup_task; | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | # Track our current directory so the task can feel free to do what | 
| 70 |  |  |  |  |  |  | # it wants | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | my $pwd = rel2abs( curdir ); | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  | $self->notify_observers( progress => 'Starting task' ); | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | eval { $self->run_task }; | 
| 77 |  |  |  |  |  |  | my $error = $@; | 
| 78 |  |  |  |  |  |  | if ( $error ) { | 
| 79 |  |  |  |  |  |  | $self->notify_observers( progress => 'Failed task' ); | 
| 80 |  |  |  |  |  |  | $self->param( task_failed => 'yes' ); | 
| 81 |  |  |  |  |  |  | $self->param( task_error  => "$error" ); | 
| 82 |  |  |  |  |  |  | } | 
| 83 |  |  |  |  |  |  | $self->tear_down_task; | 
| 84 |  |  |  |  |  |  | chdir( $pwd ); | 
| 85 |  |  |  |  |  |  | if ( $error ) { | 
| 86 |  |  |  |  |  |  | oi_error $error; | 
| 87 |  |  |  |  |  |  | } | 
| 88 |  |  |  |  |  |  | $self->notify_observers( progress => 'Task complete' ); | 
| 89 |  |  |  |  |  |  | return $self->get_status; | 
| 90 |  |  |  |  |  |  | } | 
| 91 |  |  |  |  |  |  |  | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | ######################################## | 
| 94 |  |  |  |  |  |  | # STANDARD PARAMETER DESCRIPTIONS AND DESCRIPTORS | 
| 95 |  |  |  |  |  |  |  | 
| 96 |  |  |  |  |  |  | sub get_param_description { | 
| 97 |  |  |  |  |  |  | my ( $self, $param_name ) = @_; | 
| 98 |  |  |  |  |  |  | if ( $param_name eq 'source_dir' ) { | 
| 99 |  |  |  |  |  |  | return "OpenInteract2 source directory, or at least a directory with " . | 
| 100 |  |  |  |  |  |  | "the 'pkg/' and 'sample/' directories from the distribution."; | 
| 101 |  |  |  |  |  |  | } | 
| 102 |  |  |  |  |  |  | elsif ( $param_name eq 'website_dir' ) { | 
| 103 |  |  |  |  |  |  | return "Functional OpenInteract2 website directory"; | 
| 104 |  |  |  |  |  |  | } | 
| 105 |  |  |  |  |  |  | elsif ( $param_name eq 'package_list_file' ) { | 
| 106 |  |  |  |  |  |  | return "Filename with packages to process, one per line"; | 
| 107 |  |  |  |  |  |  | } | 
| 108 |  |  |  |  |  |  | elsif ( $param_name eq 'package' ) { | 
| 109 |  |  |  |  |  |  | return "One or more packages to process"; | 
| 110 |  |  |  |  |  |  | } | 
| 111 |  |  |  |  |  |  | return 'no description available'; | 
| 112 |  |  |  |  |  |  | } | 
| 113 |  |  |  |  |  |  |  | 
| 114 |  |  |  |  |  |  | sub _get_source_dir_param { | 
| 115 |  |  |  |  |  |  | my ( $self ) = @_; | 
| 116 |  |  |  |  |  |  | return { | 
| 117 |  |  |  |  |  |  | description => $self->get_param_description( 'source_dir' ), | 
| 118 |  |  |  |  |  |  | is_required => 'yes', | 
| 119 |  |  |  |  |  |  | default     => cwd(), | 
| 120 |  |  |  |  |  |  | } | 
| 121 |  |  |  |  |  |  | } | 
| 122 |  |  |  |  |  |  |  | 
| 123 |  |  |  |  |  |  | ######################################## | 
| 124 |  |  |  |  |  |  | # PARAMETER CHECKING | 
| 125 |  |  |  |  |  |  |  | 
| 126 |  |  |  |  |  |  | # Wrapper for all check methods | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  | sub check_parameters { | 
| 129 |  |  |  |  |  |  | my ( $self ) = @_; | 
| 130 |  |  |  |  |  |  | $self->_init_setup_packages; | 
| 131 |  |  |  |  |  |  | $self->param_initialize(); | 
| 132 |  |  |  |  |  |  | my $params = $self->get_parameters(); | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  | # First check parameters that are required | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | my @field_notfound = (); | 
| 137 |  |  |  |  |  |  | while ( my ( $name, $info ) = each %{ $params } ) { | 
| 138 |  |  |  |  |  |  | next unless ( $info->{is_required} eq 'yes' ); | 
| 139 |  |  |  |  |  |  | unless ( $self->param( $name ) ) { | 
| 140 |  |  |  |  |  |  | push @field_notfound, $name; | 
| 141 |  |  |  |  |  |  | } | 
| 142 |  |  |  |  |  |  | } | 
| 143 |  |  |  |  |  |  | if ( scalar @field_notfound ) { | 
| 144 |  |  |  |  |  |  | my %err = map { $_ => 'Required parameter not defined' } | 
| 145 |  |  |  |  |  |  | @field_notfound; | 
| 146 |  |  |  |  |  |  | oi_param_error "A value for one or more required parameters ", | 
| 147 |  |  |  |  |  |  | "was not found.", | 
| 148 |  |  |  |  |  |  | { parameter_fail => \%err }; | 
| 149 |  |  |  |  |  |  | } | 
| 150 |  |  |  |  |  |  |  | 
| 151 |  |  |  |  |  |  | # Now do validatable parameters | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  | my %field_invalid = (); | 
| 154 |  |  |  |  |  |  | while ( my ( $name, $info ) = each %{ $params } ) { | 
| 155 |  |  |  |  |  |  | my $do_validate = ( ( defined $info->{is_required} and $info->{is_required} eq 'yes' ) || | 
| 156 |  |  |  |  |  |  | ( defined $info->{do_validate} and $info->{do_validate} eq 'yes' ) ); | 
| 157 |  |  |  |  |  |  | next unless ( $do_validate ); | 
| 158 |  |  |  |  |  |  | my $value = $self->param( $name ); | 
| 159 |  |  |  |  |  |  | my @errors = grep { defined $_ } $self->validate_param( $name, $value ); | 
| 160 |  |  |  |  |  |  | if ( scalar @errors ) { | 
| 161 |  |  |  |  |  |  | $field_invalid{ $name } = \@errors | 
| 162 |  |  |  |  |  |  | } | 
| 163 |  |  |  |  |  |  | } | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  | if ( scalar keys %field_invalid ) { | 
| 166 |  |  |  |  |  |  | oi_param_error "One or more parameters failed a validity check", | 
| 167 |  |  |  |  |  |  | { parameter_fail => \%field_invalid }; | 
| 168 |  |  |  |  |  |  | } | 
| 169 |  |  |  |  |  |  | } | 
| 170 |  |  |  |  |  |  |  | 
| 171 |  |  |  |  |  |  |  | 
| 172 |  |  |  |  |  |  | # Validate the given parameter -- these are built-in for everyone to | 
| 173 |  |  |  |  |  |  | # use | 
| 174 |  |  |  |  |  |  |  | 
| 175 |  |  |  |  |  |  | sub validate_param { | 
| 176 |  |  |  |  |  |  | my ( $self, $param_name, $value ) = @_; | 
| 177 |  |  |  |  |  |  | if ( $param_name eq 'source_dir' ) { | 
| 178 |  |  |  |  |  |  | return $self->_check_source_dir( $value ); | 
| 179 |  |  |  |  |  |  | } | 
| 180 |  |  |  |  |  |  | elsif ( $param_name eq 'website_dir' ) { | 
| 181 |  |  |  |  |  |  | unless ( -d $value ) { | 
| 182 |  |  |  |  |  |  | return "Value for 'website_dir' ($value) must be a " . | 
| 183 |  |  |  |  |  |  | "valid directory"; | 
| 184 |  |  |  |  |  |  | } | 
| 185 |  |  |  |  |  |  | } | 
| 186 |  |  |  |  |  |  | elsif ( $param_name eq 'package_file' ) { | 
| 187 |  |  |  |  |  |  | unless ( -f $value ) { | 
| 188 |  |  |  |  |  |  | return "Value for 'package_file' ($value) must specify " . | 
| 189 |  |  |  |  |  |  | "a valid file"; | 
| 190 |  |  |  |  |  |  | } | 
| 191 |  |  |  |  |  |  | } | 
| 192 |  |  |  |  |  |  | return undef; | 
| 193 |  |  |  |  |  |  | } | 
| 194 |  |  |  |  |  |  |  | 
| 195 |  |  |  |  |  |  | sub _check_source_dir { | 
| 196 |  |  |  |  |  |  | my ( $self, $source_dir ) = @_; | 
| 197 |  |  |  |  |  |  | unless ( -d $source_dir ) { | 
| 198 |  |  |  |  |  |  | return "Value for 'source_dir' ($source_dir) is not a valid directory"; | 
| 199 |  |  |  |  |  |  | } | 
| 200 |  |  |  |  |  |  | foreach my $distrib_dir ( qw( pkg sample ) ) { | 
| 201 |  |  |  |  |  |  | my $full_distrib_dir = catdir( $source_dir, $distrib_dir ); | 
| 202 |  |  |  |  |  |  | unless ( -d $full_distrib_dir ) { | 
| 203 |  |  |  |  |  |  | return "The 'source_dir' must contain valid subdirectory " . | 
| 204 |  |  |  |  |  |  | "[$distrib_dir]"; | 
| 205 |  |  |  |  |  |  | } | 
| 206 |  |  |  |  |  |  | } | 
| 207 |  |  |  |  |  |  | return; | 
| 208 |  |  |  |  |  |  | } | 
| 209 |  |  |  |  |  |  |  | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  | ######################################## | 
| 212 |  |  |  |  |  |  | # PARAMETER INITIALIZATION | 
| 213 |  |  |  |  |  |  |  | 
| 214 |  |  |  |  |  |  | # If package exist, reads in the SYSTEM value, the | 
| 215 |  |  |  |  |  |  | # package_list_file, etc. | 
| 216 |  |  |  |  |  |  |  | 
| 217 |  |  |  |  |  |  | sub _init_setup_packages { | 
| 218 |  |  |  |  |  |  | my ( $self ) = @_; | 
| 219 |  |  |  |  |  |  | my $initial_packages = $self->param( 'package' ); | 
| 220 |  |  |  |  |  |  | return unless ( $initial_packages ); | 
| 221 |  |  |  |  |  |  | if ( ref $initial_packages ne 'ARRAY' ) { | 
| 222 |  |  |  |  |  |  | $self->param( package => [ $initial_packages ] ); | 
| 223 |  |  |  |  |  |  | } | 
| 224 |  |  |  |  |  |  | $self->_init_setup_comma_packages; | 
| 225 |  |  |  |  |  |  | $self->_init_setup_package_groups; | 
| 226 |  |  |  |  |  |  | $self->_init_read_packages_from_file; | 
| 227 |  |  |  |  |  |  |  | 
| 228 |  |  |  |  |  |  | # Remove dupes | 
| 229 |  |  |  |  |  |  |  | 
| 230 |  |  |  |  |  |  | my $packages = $self->param( 'package' ); | 
| 231 |  |  |  |  |  |  | if ( ref $packages eq 'ARRAY' ) { | 
| 232 |  |  |  |  |  |  | my %names = map { $_ => 1 } @{ $packages }; | 
| 233 |  |  |  |  |  |  | $self->param( package => [ sort keys %names ] ); | 
| 234 |  |  |  |  |  |  | } | 
| 235 |  |  |  |  |  |  | } | 
| 236 |  |  |  |  |  |  |  | 
| 237 |  |  |  |  |  |  | # allows --package=x,y --package=z to be combined; assumes 'package' | 
| 238 |  |  |  |  |  |  | # param is already an arrayref | 
| 239 |  |  |  |  |  |  |  | 
| 240 |  |  |  |  |  |  | sub _init_setup_comma_packages { | 
| 241 |  |  |  |  |  |  | my ( $self ) = @_; | 
| 242 |  |  |  |  |  |  | my $packages = $self->param( 'package' ); | 
| 243 |  |  |  |  |  |  | $self->param( package => [ split( /\s*,\s*/, join( ',', @{ $packages } ) ) ] ); | 
| 244 |  |  |  |  |  |  | } | 
| 245 |  |  |  |  |  |  |  | 
| 246 |  |  |  |  |  |  |  | 
| 247 |  |  |  |  |  |  | # Allow a special keyword for users to specify all the initial (base) | 
| 248 |  |  |  |  |  |  | # packages. This allows something like: | 
| 249 |  |  |  |  |  |  | # | 
| 250 |  |  |  |  |  |  | #   oi_manage --package=SYSTEM ... | 
| 251 |  |  |  |  |  |  | #   oi_manage --package=SYSTEM,mypkg,theirpkg ... | 
| 252 |  |  |  |  |  |  | # | 
| 253 |  |  |  |  |  |  | # and the keyword 'SYSTEM' will be replaced by all the system | 
| 254 |  |  |  |  |  |  | # packages, which can be found by doing 'oi2_manage system_packages'; | 
| 255 |  |  |  |  |  |  | # assumes 'package' param is already an arrayref | 
| 256 |  |  |  |  |  |  |  | 
| 257 |  |  |  |  |  |  | sub _init_setup_package_groups { | 
| 258 |  |  |  |  |  |  | my ( $self ) = @_; | 
| 259 |  |  |  |  |  |  | my $packages = $self->param( 'package' ); | 
| 260 |  |  |  |  |  |  | return unless ( ref $packages eq 'ARRAY' ); | 
| 261 |  |  |  |  |  |  | my %pkg_names = map { $_ => 1 } @{ $packages }; | 
| 262 |  |  |  |  |  |  | foreach my $group_key ( keys %PACKAGE_GROUPS ) { | 
| 263 |  |  |  |  |  |  | if ( exists $pkg_names{ $group_key } ) { | 
| 264 |  |  |  |  |  |  | $pkg_names{ $_ }++ for ( @{ $PACKAGE_GROUPS{ $group_key } } ); | 
| 265 |  |  |  |  |  |  | delete $pkg_names{ $group_key }; | 
| 266 |  |  |  |  |  |  | } | 
| 267 |  |  |  |  |  |  | } | 
| 268 |  |  |  |  |  |  | $self->param( package => [ sort keys %pkg_names ] ) | 
| 269 |  |  |  |  |  |  | } | 
| 270 |  |  |  |  |  |  |  | 
| 271 |  |  |  |  |  |  | # assumes 'package' param is already an arrayref | 
| 272 |  |  |  |  |  |  |  | 
| 273 |  |  |  |  |  |  | sub _init_read_packages_from_file { | 
| 274 |  |  |  |  |  |  | my ( $self ) = @_; | 
| 275 |  |  |  |  |  |  | my $filename = $self->param( 'package_list_file' ); | 
| 276 |  |  |  |  |  |  | return unless ( $filename ); | 
| 277 |  |  |  |  |  |  | unless ( -f $filename ) { | 
| 278 |  |  |  |  |  |  | oi_error "Failure reading package list file [$filename]: ", | 
| 279 |  |  |  |  |  |  | "file does not exist"; | 
| 280 |  |  |  |  |  |  | } | 
| 281 |  |  |  |  |  |  | eval { open( PKG, '<', $filename ) || die $! }; | 
| 282 |  |  |  |  |  |  | if ( $@ ) { | 
| 283 |  |  |  |  |  |  | oi_error "Failure reading package list file [$filename]: $@"; | 
| 284 |  |  |  |  |  |  | } | 
| 285 |  |  |  |  |  |  | my @read_packages = (); | 
| 286 |  |  |  |  |  |  | while (  ) { | 
| 287 |  |  |  |  |  |  | chomp; | 
| 288 |  |  |  |  |  |  | next if /^\s*\#/; | 
| 289 |  |  |  |  |  |  | next if /^\s*$/; | 
| 290 |  |  |  |  |  |  | s/^\s+//; | 
| 291 |  |  |  |  |  |  | s/\s+$//; | 
| 292 |  |  |  |  |  |  | push @read_packages, $_; | 
| 293 |  |  |  |  |  |  | } | 
| 294 |  |  |  |  |  |  | close( PKG ); | 
| 295 |  |  |  |  |  |  |  | 
| 296 |  |  |  |  |  |  | # They can also specify --package, so add those too -- don't worry | 
| 297 |  |  |  |  |  |  | # about dupes, they get weeded out later | 
| 298 |  |  |  |  |  |  |  | 
| 299 |  |  |  |  |  |  | $self->param( package => [ @read_packages, | 
| 300 |  |  |  |  |  |  | @{ $self->param( 'package' ) } ] ); | 
| 301 |  |  |  |  |  |  | } | 
| 302 |  |  |  |  |  |  |  | 
| 303 |  |  |  |  |  |  |  | 
| 304 |  |  |  |  |  |  | ######################################## | 
| 305 |  |  |  |  |  |  | # TASK LIST/CHECK | 
| 306 |  |  |  |  |  |  |  | 
| 307 |  |  |  |  |  |  | sub is_valid_task { | 
| 308 |  |  |  |  |  |  | my ( $class, $task_name ) = @_; | 
| 309 |  |  |  |  |  |  | my %tasks = map { $_ => 1 } $class->valid_tasks; | 
| 310 |  |  |  |  |  |  | return ( defined $tasks{ $task_name } ); | 
| 311 |  |  |  |  |  |  | } | 
| 312 |  |  |  |  |  |  |  | 
| 313 |  |  |  |  |  |  | sub valid_tasks { | 
| 314 |  |  |  |  |  |  | return __PACKAGE__->get_registered_types; | 
| 315 |  |  |  |  |  |  | } | 
| 316 |  |  |  |  |  |  |  | 
| 317 |  |  |  |  |  |  | sub valid_tasks_description { | 
| 318 |  |  |  |  |  |  | my ( $self ) = @_; | 
| 319 |  |  |  |  |  |  | my %tasks = map { $_ => 1 } $self->valid_tasks; | 
| 320 |  |  |  |  |  |  | foreach my $task ( keys %tasks ) { | 
| 321 |  |  |  |  |  |  | my $task_class = $self->get_factory_class( $task ); | 
| 322 |  |  |  |  |  |  | my $desc  = $task_class->get_brief_description; | 
| 323 |  |  |  |  |  |  | $tasks{ $task } = $desc; | 
| 324 |  |  |  |  |  |  | } | 
| 325 |  |  |  |  |  |  | return \%tasks; | 
| 326 |  |  |  |  |  |  | } | 
| 327 |  |  |  |  |  |  |  | 
| 328 |  |  |  |  |  |  | # Retrieves the parameter hashref for a particular task -- this can be | 
| 329 |  |  |  |  |  |  | # a class method (needs $task_name filled in) or an object method | 
| 330 |  |  |  |  |  |  |  | 
| 331 |  |  |  |  |  |  | sub task_parameters { | 
| 332 |  |  |  |  |  |  | my ( $item, $task_name ) = @_; | 
| 333 |  |  |  |  |  |  | my ( $manage ); | 
| 334 |  |  |  |  |  |  | if ( ref $item ) { | 
| 335 |  |  |  |  |  |  | $manage = $item; | 
| 336 |  |  |  |  |  |  | } | 
| 337 |  |  |  |  |  |  | else { | 
| 338 |  |  |  |  |  |  | unless ( $task_name ) { | 
| 339 |  |  |  |  |  |  | oi_error "If you call 'task_parameters' as a class method ", | 
| 340 |  |  |  |  |  |  | "you must pass the task name as the only argument."; | 
| 341 |  |  |  |  |  |  | } | 
| 342 |  |  |  |  |  |  | $manage = $item->new( $task_name ); | 
| 343 |  |  |  |  |  |  | } | 
| 344 |  |  |  |  |  |  | my $params = $manage->get_parameters; | 
| 345 |  |  |  |  |  |  | my %basic_params = (); | 
| 346 |  |  |  |  |  |  | while ( my ( $name, $info ) = each %{ $params } ) { | 
| 347 |  |  |  |  |  |  | $info->{name} = $name; | 
| 348 |  |  |  |  |  |  | $basic_params{ $name } = $info; | 
| 349 |  |  |  |  |  |  | } | 
| 350 |  |  |  |  |  |  | return \%basic_params; | 
| 351 |  |  |  |  |  |  | } | 
| 352 |  |  |  |  |  |  |  | 
| 353 |  |  |  |  |  |  | # Retrieves all parameter names plus whether they're | 
| 354 |  |  |  |  |  |  | # boolean/multivalued | 
| 355 |  |  |  |  |  |  |  | 
| 356 |  |  |  |  |  |  | sub all_parameters { | 
| 357 |  |  |  |  |  |  | my ( $class ) = @_; | 
| 358 |  |  |  |  |  |  | my %all = (); | 
| 359 |  |  |  |  |  |  | foreach my $task_name ( $class->valid_tasks ) { | 
| 360 |  |  |  |  |  |  | my $param_data = $class->task_parameters( $task_name ); | 
| 361 |  |  |  |  |  |  | next unless ( ref $param_data eq 'HASH' ); | 
| 362 |  |  |  |  |  |  | while ( my ( $name, $info ) = each %{ $param_data } ) { | 
| 363 |  |  |  |  |  |  | next if ( $all{ $name } ); | 
| 364 |  |  |  |  |  |  | $all{ $name } = $info; | 
| 365 |  |  |  |  |  |  | } | 
| 366 |  |  |  |  |  |  | } | 
| 367 |  |  |  |  |  |  | return \%all; | 
| 368 |  |  |  |  |  |  | } | 
| 369 |  |  |  |  |  |  |  | 
| 370 |  |  |  |  |  |  |  | 
| 371 |  |  |  |  |  |  |  | 
| 372 |  |  |  |  |  |  | sub all_parameters_long_options { | 
| 373 |  |  |  |  |  |  | my ( $class ) = @_; | 
| 374 |  |  |  |  |  |  | my $all_params = $class->all_parameters; | 
| 375 |  |  |  |  |  |  | my @opt = (); | 
| 376 |  |  |  |  |  |  | while ( my ( $name, $info ) = each %{ $all_params } ) { | 
| 377 |  |  |  |  |  |  | if ( defined $info->{is_boolean} and | 
| 378 |  |  |  |  |  |  | $info->{is_boolean} eq 'yes' ) { | 
| 379 |  |  |  |  |  |  | push @opt, $name; | 
| 380 |  |  |  |  |  |  | } | 
| 381 |  |  |  |  |  |  | elsif ( defined $info->{is_multivalued} and | 
| 382 |  |  |  |  |  |  | $info->{is_multivalued} eq 'yes' ) { | 
| 383 |  |  |  |  |  |  | push @opt, "$name=s@"; | 
| 384 |  |  |  |  |  |  | } | 
| 385 |  |  |  |  |  |  | else { | 
| 386 |  |  |  |  |  |  | push @opt, "$name=s"; | 
| 387 |  |  |  |  |  |  | } | 
| 388 |  |  |  |  |  |  | } | 
| 389 |  |  |  |  |  |  | return @opt; | 
| 390 |  |  |  |  |  |  | } | 
| 391 |  |  |  |  |  |  |  | 
| 392 |  |  |  |  |  |  | ######################################## | 
| 393 |  |  |  |  |  |  | # PARAMETERS | 
| 394 |  |  |  |  |  |  |  | 
| 395 |  |  |  |  |  |  | sub param_copy_from { | 
| 396 |  |  |  |  |  |  | my ( $self, $other_task ) = @_; | 
| 397 |  |  |  |  |  |  | $self->param_assign( $other_task->param ); | 
| 398 |  |  |  |  |  |  | return $self->param; | 
| 399 |  |  |  |  |  |  | } | 
| 400 |  |  |  |  |  |  |  | 
| 401 |  |  |  |  |  |  |  | 
| 402 |  |  |  |  |  |  | ######################################## | 
| 403 |  |  |  |  |  |  | # STATUS | 
| 404 |  |  |  |  |  |  |  | 
| 405 |  |  |  |  |  |  | sub _add_status { | 
| 406 |  |  |  |  |  |  | my ( $self, @status ) = @_; | 
| 407 |  |  |  |  |  |  | push @{ $self->{_status} }, @status; | 
| 408 |  |  |  |  |  |  | foreach my $hr ( @status ) { | 
| 409 |  |  |  |  |  |  | $self->notify_observers( status => $hr ); | 
| 410 |  |  |  |  |  |  | } | 
| 411 |  |  |  |  |  |  | return $self->{_status}; | 
| 412 |  |  |  |  |  |  | } | 
| 413 |  |  |  |  |  |  |  | 
| 414 |  |  |  |  |  |  | sub _add_status_head { | 
| 415 |  |  |  |  |  |  | my ( $self, @status ) = @_; | 
| 416 |  |  |  |  |  |  | unshift @{ $self->{_status} }, @status; | 
| 417 |  |  |  |  |  |  | foreach my $hr ( @status ) { | 
| 418 |  |  |  |  |  |  | $self->notify_observers( status => $hr ); | 
| 419 |  |  |  |  |  |  | } | 
| 420 |  |  |  |  |  |  | return $self->{_status}; | 
| 421 |  |  |  |  |  |  | } | 
| 422 |  |  |  |  |  |  |  | 
| 423 |  |  |  |  |  |  | sub get_status { | 
| 424 |  |  |  |  |  |  | my ( $self ) = @_; | 
| 425 |  |  |  |  |  |  | return @{ $self->{_status} }; | 
| 426 |  |  |  |  |  |  | } | 
| 427 |  |  |  |  |  |  |  | 
| 428 |  |  |  |  |  |  | sub merge_status_by_action { | 
| 429 |  |  |  |  |  |  | my ( $item, @status ) = @_; | 
| 430 |  |  |  |  |  |  | if ( scalar @status == 0 | 
| 431 |  |  |  |  |  |  | and UNIVERSAL::isa( $item, 'OpenInteract2::Manage' ) ) { | 
| 432 |  |  |  |  |  |  | @status = $item->get_status; | 
| 433 |  |  |  |  |  |  | } | 
| 434 |  |  |  |  |  |  | my $current_action = ''; | 
| 435 |  |  |  |  |  |  | my @tmp_status = (); | 
| 436 |  |  |  |  |  |  | my @new_status = (); | 
| 437 |  |  |  |  |  |  | foreach my $s ( @status ) { | 
| 438 |  |  |  |  |  |  | unless ( $current_action ) { | 
| 439 |  |  |  |  |  |  | $current_action = $s->{action}; | 
| 440 |  |  |  |  |  |  | } | 
| 441 |  |  |  |  |  |  | if ( defined $s->{action} and $s->{action} ne $current_action ) { | 
| 442 |  |  |  |  |  |  | push @new_status, { action => $current_action, | 
| 443 |  |  |  |  |  |  | status => [ @tmp_status ] }; | 
| 444 |  |  |  |  |  |  | @tmp_status = (); | 
| 445 |  |  |  |  |  |  | $current_action = $s->{action}; | 
| 446 |  |  |  |  |  |  | } | 
| 447 |  |  |  |  |  |  | push @tmp_status, $s; | 
| 448 |  |  |  |  |  |  | } | 
| 449 |  |  |  |  |  |  | if ( scalar @tmp_status > 0 ) { | 
| 450 |  |  |  |  |  |  | push @new_status, { action => $current_action, | 
| 451 |  |  |  |  |  |  | status => \@tmp_status }; | 
| 452 |  |  |  |  |  |  | } | 
| 453 |  |  |  |  |  |  | return @new_status; | 
| 454 |  |  |  |  |  |  | } | 
| 455 |  |  |  |  |  |  |  | 
| 456 |  |  |  |  |  |  | # shortcut for adding bad/good status | 
| 457 |  |  |  |  |  |  |  | 
| 458 |  |  |  |  |  |  | sub _fail { | 
| 459 |  |  |  |  |  |  | my ( $self, $action, $msg, %additional ) = @_; | 
| 460 |  |  |  |  |  |  | $self->_add_status({ | 
| 461 |  |  |  |  |  |  | is_ok    => 'no', | 
| 462 |  |  |  |  |  |  | action   => $action, | 
| 463 |  |  |  |  |  |  | message  => $msg, | 
| 464 |  |  |  |  |  |  | %additional, | 
| 465 |  |  |  |  |  |  | }); | 
| 466 |  |  |  |  |  |  | return; | 
| 467 |  |  |  |  |  |  | } | 
| 468 |  |  |  |  |  |  |  | 
| 469 |  |  |  |  |  |  | sub _ok { | 
| 470 |  |  |  |  |  |  | my ( $self, $action, $msg, %additional ) = @_; | 
| 471 |  |  |  |  |  |  | $self->_add_status({ | 
| 472 |  |  |  |  |  |  | is_ok    => 'yes', | 
| 473 |  |  |  |  |  |  | action   => $action, | 
| 474 |  |  |  |  |  |  | message  => $msg, | 
| 475 |  |  |  |  |  |  | %additional, | 
| 476 |  |  |  |  |  |  | }); | 
| 477 |  |  |  |  |  |  | return; | 
| 478 |  |  |  |  |  |  | } | 
| 479 |  |  |  |  |  |  |  | 
| 480 |  |  |  |  |  |  |  | 
| 481 |  |  |  |  |  |  |  | 
| 482 |  |  |  |  |  |  | ######################################## | 
| 483 |  |  |  |  |  |  | # INFRASTRUCTURE (SUBCLASSES) | 
| 484 |  |  |  |  |  |  |  | 
| 485 |  |  |  |  |  |  | sub _setup_context { | 
| 486 |  |  |  |  |  |  | my ( $self, $params ) = @_; | 
| 487 |  |  |  |  |  |  |  | 
| 488 |  |  |  |  |  |  | # don't recreate the context every time | 
| 489 |  |  |  |  |  |  | eval { OpenInteract2::Context->instance }; | 
| 490 |  |  |  |  |  |  | return unless ( $@ ); | 
| 491 |  |  |  |  |  |  |  | 
| 492 |  |  |  |  |  |  | my $log = get_logger(); | 
| 493 |  |  |  |  |  |  | if ( $self->param( 'debug' ) ) { | 
| 494 |  |  |  |  |  |  | $log->level( $DEBUG ); | 
| 495 |  |  |  |  |  |  | } | 
| 496 |  |  |  |  |  |  | my $website_dir = $self->param( 'website_dir' ); | 
| 497 |  |  |  |  |  |  | unless ( -d $website_dir ) { | 
| 498 |  |  |  |  |  |  | oi_error "Cannot open context with invalid website ", | 
| 499 |  |  |  |  |  |  | "directory '$website_dir'"; | 
| 500 |  |  |  |  |  |  | } | 
| 501 |  |  |  |  |  |  | $log->info( "Website directory '$website_dir' exists, setting up context..." ); | 
| 502 |  |  |  |  |  |  | my $bootstrap = OpenInteract2::Config::Bootstrap->new({ | 
| 503 |  |  |  |  |  |  | website_dir => $website_dir | 
| 504 |  |  |  |  |  |  | }); | 
| 505 |  |  |  |  |  |  | $log->info( "Created bootstrap config ok, creating context..." ); | 
| 506 |  |  |  |  |  |  | OpenInteract2::Context->create( $bootstrap, $params ); | 
| 507 |  |  |  |  |  |  | $log->info( "Context setup for management task(s) ok" ); | 
| 508 |  |  |  |  |  |  | } | 
| 509 |  |  |  |  |  |  |  | 
| 510 |  |  |  |  |  |  | # Creates status entry with all files removed/skipped/updated | 
| 511 |  |  |  |  |  |  |  | 
| 512 |  |  |  |  |  |  | sub _set_copy_file_status { | 
| 513 |  |  |  |  |  |  | my ( $self, $status ) = @_; | 
| 514 |  |  |  |  |  |  | $status->{copied}  ||= []; | 
| 515 |  |  |  |  |  |  | $status->{skipped} ||= []; | 
| 516 |  |  |  |  |  |  | $status->{same}    ||= []; | 
| 517 |  |  |  |  |  |  | foreach my $file ( @{ $status->{copied} } ) { | 
| 518 |  |  |  |  |  |  | $self->_ok( | 
| 519 |  |  |  |  |  |  | 'copy updated template files', | 
| 520 |  |  |  |  |  |  | "File $file copied", | 
| 521 |  |  |  |  |  |  | filename => $file | 
| 522 |  |  |  |  |  |  | ); | 
| 523 |  |  |  |  |  |  | } | 
| 524 |  |  |  |  |  |  | foreach my $file ( @{ $status->{skipped} } ) { | 
| 525 |  |  |  |  |  |  | $self->_ok( | 
| 526 |  |  |  |  |  |  | 'copy updated template files', | 
| 527 |  |  |  |  |  |  | "File $file skipped, marked as read-only", | 
| 528 |  |  |  |  |  |  | filename => $file | 
| 529 |  |  |  |  |  |  | ); | 
| 530 |  |  |  |  |  |  | } | 
| 531 |  |  |  |  |  |  | foreach my $file ( @{ $status->{same} } ) { | 
| 532 |  |  |  |  |  |  | $self->_ok( | 
| 533 |  |  |  |  |  |  | 'copy updated template files', | 
| 534 |  |  |  |  |  |  | "File $file skipped, source and destination same", | 
| 535 |  |  |  |  |  |  | filename => $file | 
| 536 |  |  |  |  |  |  | ); | 
| 537 |  |  |  |  |  |  | } | 
| 538 |  |  |  |  |  |  | } | 
| 539 |  |  |  |  |  |  |  | 
| 540 |  |  |  |  |  |  | ######################################## | 
| 541 |  |  |  |  |  |  | # FACTORY | 
| 542 |  |  |  |  |  |  |  | 
| 543 |  |  |  |  |  |  | sub factory_log { | 
| 544 |  |  |  |  |  |  | # no-op so we get around the l4p 'no init' msg | 
| 545 |  |  |  |  |  |  | #    my ( $self, @msg ) = @_; | 
| 546 |  |  |  |  |  |  | #    get_logger()->info( @msg ); | 
| 547 |  |  |  |  |  |  | } | 
| 548 |  |  |  |  |  |  |  | 
| 549 |  |  |  |  |  |  | sub factory_error { | 
| 550 |  |  |  |  |  |  | my ( $self, @msg ) = @_; | 
| 551 |  |  |  |  |  |  | get_logger()->error( @msg ); | 
| 552 |  |  |  |  |  |  | die @msg, "\n"; | 
| 553 |  |  |  |  |  |  | } | 
| 554 |  |  |  |  |  |  |  | 
| 555 |  |  |  |  |  |  |  | 
| 556 |  |  |  |  |  |  | ############################## | 
| 557 |  |  |  |  |  |  | # FIND ALL MANAGEMENT TASKS | 
| 558 |  |  |  |  |  |  |  | 
| 559 |  |  |  |  |  |  | OpenInteract2::Util->find_factory_subclasses( | 
| 560 |  |  |  |  |  |  | 'OpenInteract2::Manage', @INC | 
| 561 |  |  |  |  |  |  | ); | 
| 562 |  |  |  |  |  |  |  | 
| 563 |  |  |  |  |  |  |  | 
| 564 |  |  |  |  |  |  | ######################################## | 
| 565 |  |  |  |  |  |  | # INTERFACE | 
| 566 |  |  |  |  |  |  | # All are optional except run_task() | 
| 567 |  |  |  |  |  |  |  | 
| 568 |  |  |  |  |  |  | # Run at new() | 
| 569 |  |  |  |  |  |  | sub init                  {} | 
| 570 |  |  |  |  |  |  |  | 
| 571 |  |  |  |  |  |  | # Identify the name by which your task is known | 
| 572 |  |  |  |  |  |  | sub get_name              { return undef } | 
| 573 |  |  |  |  |  |  |  | 
| 574 |  |  |  |  |  |  | # Help out tools using your task and describe what it does | 
| 575 |  |  |  |  |  |  | sub get_brief_description { return 'No description available' } | 
| 576 |  |  |  |  |  |  |  | 
| 577 |  |  |  |  |  |  | # Return parameter information | 
| 578 |  |  |  |  |  |  | sub get_parameters        { return {} } | 
| 579 |  |  |  |  |  |  |  | 
| 580 |  |  |  |  |  |  | # Do the work! | 
| 581 |  |  |  |  |  |  | sub run_task              { die "Define run_task() in subclass" } | 
| 582 |  |  |  |  |  |  |  | 
| 583 |  |  |  |  |  |  | # Do work before run_task() | 
| 584 |  |  |  |  |  |  | sub setup_task            { return undef } | 
| 585 |  |  |  |  |  |  |  | 
| 586 |  |  |  |  |  |  | # Do cleanup after run_task() | 
| 587 |  |  |  |  |  |  | sub tear_down_task        { return undef } | 
| 588 |  |  |  |  |  |  |  | 
| 589 |  |  |  |  |  |  | # Do pre-validation transformations of parameters | 
| 590 |  |  |  |  |  |  | sub param_initialize      { return undef } | 
| 591 |  |  |  |  |  |  |  | 
| 592 |  |  |  |  |  |  | 1; | 
| 593 |  |  |  |  |  |  |  | 
| 594 |  |  |  |  |  |  | __END__ |