summaryrefslogtreecommitdiff
path: root/IkiWiki/Plugin/search.pm
blob: 9bf223cf000310463175c2cd579aaa9c603d9010 (plain)
  1. #!/usr/bin/perl
  2. # hyperestraier search engine plugin
  3. package IkiWiki::Plugin::search;
  4. use warnings;
  5. use strict;
  6. use IkiWiki 2.00;
  7. sub import { #{{{
  8. hook(type => "getopt", id => "hyperestraier",
  9. call => \&getopt);
  10. hook(type => "checkconfig", id => "hyperestraier",
  11. call => \&checkconfig);
  12. hook(type => "pagetemplate", id => "hyperestraier",
  13. call => \&pagetemplate);
  14. hook(type => "delete", id => "hyperestraier",
  15. call => \&delete);
  16. hook(type => "change", id => "hyperestraier",
  17. call => \&change);
  18. hook(type => "cgi", id => "hyperestraier",
  19. call => \&cgi);
  20. } # }}}
  21. sub getopt () { #{{{
  22. eval q{use Getopt::Long};
  23. error($@) if $@;
  24. Getopt::Long::Configure('pass_through');
  25. GetOptions("estseek=s" => \$config{estseek});
  26. } #}}}
  27. sub checkconfig () { #{{{
  28. foreach my $required (qw(url cgiurl)) {
  29. if (! length $config{$required}) {
  30. error(sprintf(gettext("Must specify %s when using the search plugin"), $required));
  31. }
  32. }
  33. } #}}}
  34. my $form;
  35. sub pagetemplate (@) { #{{{
  36. my %params=@_;
  37. my $page=$params{page};
  38. my $template=$params{template};
  39. # Add search box to page header.
  40. if ($template->query(name => "searchform")) {
  41. if (! defined $form) {
  42. my $searchform = template("searchform.tmpl", blind_cache => 1);
  43. $searchform->param(searchaction => $config{cgiurl});
  44. $form=$searchform->output;
  45. }
  46. $template->param(searchform => $form);
  47. }
  48. } #}}}
  49. sub delete (@) { #{{{
  50. debug(gettext("cleaning hyperestraier search index"));
  51. estcmd("purge -cl");
  52. estcfg();
  53. } #}}}
  54. sub change (@) { #{{{
  55. debug(gettext("updating hyperestraier search index"));
  56. estcmd("gather -cm -bc -cl -sd",
  57. map {
  58. map {
  59. Encode::encode_utf8($config{destdir}."/".$_)
  60. } @{$renderedfiles{pagename($_)}};
  61. } @_
  62. );
  63. estcfg();
  64. } #}}}
  65. sub cgi ($) { #{{{
  66. my $cgi=shift;
  67. if (defined $cgi->param('phrase') || defined $cgi->param("navi")) {
  68. # only works for GET requests
  69. chdir("$config{wikistatedir}/hyperestraier") || error("chdir: $!");
  70. exec("./".IkiWiki::basename($config{cgiurl})) || error("estseek.cgi failed");
  71. }
  72. } #}}}
  73. my $configured=0;
  74. sub estcfg () { #{{{
  75. return if $configured;
  76. $configured=1;
  77. my $estdir="$config{wikistatedir}/hyperestraier";
  78. my $cgi=IkiWiki::basename($config{cgiurl});
  79. $cgi=~s/\..*$//;
  80. my $newfile="$estdir/$cgi.tmpl.new";
  81. my $cleanup = sub { unlink($newfile) };
  82. open(TEMPLATE, ">:utf8", $newfile) || error("open $newfile: $!", $cleanup);
  83. print TEMPLATE IkiWiki::misctemplate("search",
  84. "<!--ESTFORM-->\n\n<!--ESTRESULT-->\n\n<!--ESTINFO-->\n\n",
  85. forcebaseurl => IkiWiki::dirname($config{cgiurl})."/") ||
  86. error("write $newfile: $!", $cleanup);
  87. close TEMPLATE || error("save $newfile: $!", $cleanup);
  88. rename($newfile, "$estdir/$cgi.tmpl") ||
  89. error("rename $newfile: $!", $cleanup);
  90. $newfile="$estdir/$cgi.conf";
  91. open(TEMPLATE, ">$newfile") || error("open $newfile: $!", $cleanup);
  92. my $template=template("estseek.conf");
  93. eval q{use Cwd 'abs_path'};
  94. $template->param(
  95. index => $estdir,
  96. tmplfile => "$estdir/$cgi.tmpl",
  97. destdir => abs_path($config{destdir}),
  98. url => $config{url},
  99. );
  100. print TEMPLATE $template->output || error("write $newfile: $!", $cleanup);
  101. close TEMPLATE || error("save $newfile: $!", $cleanup);
  102. rename($newfile, "$estdir/$cgi.conf") ||
  103. error("rename $newfile: $!", $cleanup);
  104. $cgi="$estdir/".IkiWiki::basename($config{cgiurl});
  105. unlink($cgi);
  106. my $estseek = defined $config{estseek} ? $config{estseek} : '/usr/lib/estraier/estseek.cgi';
  107. symlink($estseek, $cgi) || error("symlink $estseek $cgi: $!");
  108. } # }}}
  109. sub estcmd ($;@) { #{{{
  110. my @params=split(' ', shift);
  111. push @params, "-cl", "$config{wikistatedir}/hyperestraier";
  112. if (@_) {
  113. push @params, "-";
  114. }
  115. my $pid=open(CHILD, "|-");
  116. if ($pid) {
  117. # parent
  118. foreach (@_) {
  119. print CHILD "$_\n";
  120. }
  121. close(CHILD) || print STDERR "estcmd @params exited nonzero: $?\n";
  122. }
  123. else {
  124. # child
  125. open(STDOUT, "/dev/null"); # shut it up (closing won't work)
  126. exec("estcmd", @params) || error("can't run estcmd");
  127. }
  128. } #}}}
  129. 1
gt;{dbh};
  • $form->{customer_id} ||= 'NULL';
  • $form->{projectnumber} =
  • $form->update_defaults( $myconfig, "projectnumber", $dbh )
  • unless $form->{projectnumber};
  • my $enddate;
  • my $startdate;
  • $enddate = $form->{enddate} if $form->{enddate};
  • $startdate = $form->{startdate} if $form->{startdate};
  • if ( $form->{id} ) {
  • $query = qq|
  • UPDATE project
  • SET projectnumber = ?,
  • description = ?,
  • startdate = ?,
  • enddate = ?,
  • customer_id = ?
  • WHERE id = | . $dbh->quote( $form->{id} );
  • }
  • else {
  • $query = qq|
  • INSERT INTO project (projectnumber, description,
  • startdate, enddate, customer_id)
  • VALUES (?, ?, ?, ?, ?)|;
  • }
  • $sth = $dbh->prepare($query);
  • $sth->execute( $form->{projectnumber},
  • $form->{description}, $startdate, $enddate, $form->{customer_id} )
  • || $form->dberror($query);
  • $form->run_custom_queries( 'project', 'UPDATE' );
  • $dbh->commit;
  • }
  • sub list_stock {
  • my ( $self, $myconfig, $form ) = @_;
  • my $dbh = $form->{dbh};
  • my $var;
  • my $where = "1 = 1";
  • if ( $form->{status} eq 'active' ) {
  • $where = qq|
  • (pr.enddate IS NULL OR pr.enddate >= current_date)
  • AND pr.completed < pr.production|;
  • }
  • if ( $form->{status} eq 'inactive' ) {
  • $where = qq|pr.completed = pr.production|;
  • }
  • if ( $form->{projectnumber} ) {
  • $var = $dbh->quote( $form->like( lc $form->{projectnumber} ) );
  • $where .= " AND lower(pr.projectnumber) LIKE $var";
  • }
  • if ( $form->{description} ) {
  • $var = $dbh->quote( $form->like( lc $form->{description} ) );
  • $where .= " AND lower(pr.description) LIKE $var";
  • }
  • $form->{sort} = "projectnumber" unless $form->{sort};
  • my @a = ( $form->{sort} );
  • my %ordinal = ( projectnumber => 2, description => 3 );
  • my $sortorder = $form->sort_order( \@a, \%ordinal );
  • my $query = qq|
  • SELECT pr.*, p.partnumber
  • FROM project pr
  • JOIN parts p ON (p.id = pr.parts_id)
  • WHERE $where
  • ORDER BY $sortorder|;
  • $sth = $dbh->prepare($query);
  • $sth->execute || $form->dberror($query);
  • while ( my $ref = $sth->fetchrow_hashref(NAME_lc) ) {
  • push @{ $form->{all_project} }, $ref;
  • }
  • $sth->finish;
  • $query = qq|SELECT current_date|;
  • ( $form->{stockingdate} ) = $dbh->selectrow_array($query)
  • if !$form->{stockingdate};
  • $dbh->commit;
  • }
  • sub jobs {
  • my ( $self, $myconfig, $form ) = @_;
  • my $dbh = $form->{dbh};
  • $form->{sort} = "projectnumber" unless $form->{sort};
  • my @a = ( $form->{sort} );
  • my %ordinal = ( projectnumber => 2, description => 3, startdate => 4 );
  • my $sortorder = $form->sort_order( \@a, \%ordinal );
  • my $query = qq|
  • SELECT pr.*, p.partnumber, p.onhand, c.name
  • FROM project pr
  • JOIN parts p ON (p.id = pr.parts_id)
  • LEFT JOIN customer c ON (c.id = pr.customer_id)
  • WHERE 1=1|;
  • if ( $form->{projectnumber} ne "" ) {
  • $var = $dbh->quote( $form->like( lc $form->{projectnumber} ) );
  • $query .= " AND lower(pr.projectnumber) LIKE $var";
  • }
  • if ( $form->{description} ne "" ) {
  • $var = $dbh->quote( $form->like( lc $form->{description} ) );
  • $query .= " AND lower(pr.description) LIKE $var";
  • }
  • ( $form->{startdatefrom}, $form->{startdateto} ) =
  • $form->from_to( $form->{year}, $form->{month}, $form->{interval} )
  • if $form->{year} && $form->{month};
  • if ( $form->{startdatefrom} ) {
  • $query .=
  • " AND pr.startdate >= " . $dbh->quote( $form->{startdatefrom} );
  • }
  • if ( $form->{startdateto} ) {
  • $query .= " AND pr.startdate <= " . $dbh->quote( $form->{startdateto} );
  • }
  • if ( $form->{status} eq 'active' ) {
  • $query .= qq| AND NOT pr.production = pr.completed|;
  • }
  • if ( $form->{status} eq 'inactive' ) {
  • $query .= qq| AND pr.production = pr.completed|;
  • }
  • if ( $form->{status} eq 'orphaned' ) {
  • $query .= qq|
  • AND pr.completed = 0
  • AND (pr.id NOT IN
  • (SELECT DISTINCT project_id
  • FROM invoice
  • WHERE project_id > 0
  • UNION
  • SELECT DISTINCT project_id
  • FROM orderitems
  • WHERE project_id > 0
  • UNION
  • SELECT DISTINCT project_id
  • FROM jcitems
  • WHERE project_id > 0)
  • )|;
  • }
  • $query .= qq|
  • ORDER BY $sortorder|;
  • $sth = $dbh->prepare($query);
  • $sth->execute || $form->dberror($query);
  • while ( my $ref = $sth->fetchrow_hashref(NAME_lc) ) {
  • push @{ $form->{all_project} }, $ref;
  • }
  • $sth->finish;
  • $dbh->commit;
  • }
  • sub get_job {
  • my ( $self, $myconfig, $form ) = @_;
  • # connect to database
  • my $dbh = $form->{dbh};
  • my $query;
  • my $sth;
  • my $ref;
  • if ( $form->{id} ) {
  • $query = qq|
  • SELECT value FROM defaults
  • WHERE setting_key = 'weightunit'|;
  • ( $form->{weightunit} ) = $dbh->selectrow_array($query);
  • $query = qq|
  • SELECT pr.*, p.partnumber,
  • p.description AS partdescription, p.unit,
  • p.listprice, p.sellprice, p.priceupdate,
  • p.weight, p.notes, p.bin, p.partsgroup_id,
  • ch.accno AS income_accno,
  • ch.description AS income_description,
  • pr.customer_id, c.name AS customer,
  • pg.partsgroup
  • FROM project pr
  • LEFT JOIN parts p ON (p.id = pr.parts_id)
  • LEFT JOIN chart ch ON (ch.id = p.income_accno_id)
  • LEFT JOIN customer c ON (c.id = pr.customer_id)
  • LEFT JOIN partsgroup pg ON (pg.id = p.partsgroup_id)
  • WHERE pr.id = | . $dbh->quote( $form->{id} );
  • }
  • else {
  • $query = qq|
  • SELECT value, current_date AS startdate FROM defaults
  • WHERE setting_key = 'weightunit'|;
  • }
  • $sth = $dbh->prepare($query);
  • $sth->execute || $form->dberror($query);
  • $ref = $sth->fetchrow_hashref(NAME_lc);
  • for ( keys %$ref ) { $form->{$_} = $ref->{$_} }
  • $sth->finish;
  • if ( $form->{id} ) {
  • # check if it is orphaned
  • $query = qq|
  • SELECT count(*)
  • FROM invoice
  • WHERE project_id = ?
  • UNION
  • SELECT count(*)
  • FROM orderitems
  • WHERE project_id = ?
  • UNION
  • SELECT count(*)
  • FROM jcitems
  • WHERE project_id = ?|;
  • $sth = $dbh->prepare($query);
  • $sth->execute( $form->{id}, $form->{id}, $form->{id} )
  • || $form->dberror($query);
  • my $count;
  • my $count;
  • while ( ($count) = $sth->fetchrow_array ) {
  • $form->{orphaned} += $count;
  • }
  • $sth->finish;
  • }
  • $form->{orphaned} = !$form->{orphaned};
  • $query = qq|
  • SELECT accno, description, link
  • FROM chart
  • WHERE link LIKE ?
  • ORDER BY accno|;
  • $sth = $dbh->prepare($query);
  • $sth->execute('%IC%') || $form->dberror($query);
  • while ( $ref = $sth->fetchrow_hashref(NAME_lc) ) {
  • for ( split /:/, $ref->{link} ) {
  • if (/IC/) {
  • push @{ $form->{IC_links}{$_} },
  • {
  • accno => $ref->{accno},
  • description => $ref->{description}
  • };
  • }
  • }
  • }
  • $sth->finish;
  • if ( $form->{id} ) {
  • $query = qq|
  • SELECT ch.accno
  • FROM parts p
  • JOIN partstax pt ON (pt.parts_id = p.id)
  • JOIN chart ch ON (pt.chart_id = ch.id)
  • WHERE p.id = ?|;
  • $sth = $dbh->prepare($query);
  • $sth->execute( $form->{id} ) || $form->dberror($query);
  • while ( $ref = $sth->fetchrow_hashref(NAME_lc) ) {
  • $form->{amount}{ $ref->{accno} } = $ref->{accno};
  • }
  • $sth->finish;
  • }
  • PE->get_customer( $myconfig, $form, $dbh );
  • $dbh->commit;
  • }
  • sub get_customer {
  • my ( $self, $myconfig, $form, $dbh ) = @_;
  • if ( !$dbh ) {
  • $dbh = $form->{dbh};
  • }
  • my $query;
  • my $sth;
  • my $ref;
  • if ( !$form->{startdate} ) {
  • $query = qq|SELECT current_date|;
  • ( $form->{startdate} ) = $dbh->selectrow_array($query);
  • }
  • my $where =
  • qq|(startdate >= |
  • . $dbh->quote( $form->{startdate} )
  • . qq| OR startdate IS NULL OR enddate IS NULL)|;
  • if ( $form->{enddate} ) {
  • $where .=
  • qq| AND (enddate >= |
  • . $dbh->quote( $form->{enddate} )
  • . qq| OR enddate IS NULL)|;
  • }
  • else {
  • $where .= qq| AND (enddate >= current_date OR enddate IS NULL)|;
  • }
  • $query = qq|
  • SELECT count(*)
  • FROM customer
  • WHERE $where|;
  • my ($count) = $dbh->selectrow_array($query);
  • if ( $count < $myconfig->{vclimit} ) {
  • $query = qq|
  • SELECT id, name
  • FROM customer
  • WHERE $where|;
  • if ( $form->{customer_id} ) {
  • $query .= qq|
  • UNION
  • SELECT id,name
  • FROM customer
  • WHERE id = | . $dbh->quote( $form->{customer_id} );
  • }
  • $query .= qq|
  • ORDER BY name|;
  • $sth = $dbh->prepare($query);
  • $sth->execute || $form->dberror($query);
  • @{ $form->{all_customer} } = ();
  • while ( $ref = $sth->fetchrow_hashref(NAME_lc) ) {
  • push @{ $form->{all_customer} }, $ref;
  • }
  • $sth->finish;
  • }
  • }
  • sub save_job {
  • my ( $self, $myconfig, $form ) = @_;
  • my $dbh = $form->{dbh};
  • my ($income_accno) = split /--/, $form->{IC_income};
  • my ( $partsgroup, $partsgroup_id ) = split /--/, $form->{partsgroup};
  • if ( $form->{id} ) {
  • $query = qq|
  • SELECT id FROM project
  • WHERE id = | . $dbh->quote( $form->{id} );
  • ( $form->{id} ) = $dbh->selectrow_array($query);
  • }
  • if ( !$form->{id} ) {
  • my $uid = localtime;
  • $uid .= "$$";
  • $query = qq|
  • INSERT INTO project (projectnumber)
  • VALUES ('$uid')|;
  • $dbh->do($query) || $form->dberror($query);
  • $query = qq|
  • SELECT id FROM project
  • WHERE projectnumber = '$uid'|;
  • ( $form->{id} ) = $dbh->selectrow_array($query);
  • }
  • $form->{projectnumber} =
  • $form->update_defaults( $myconfig, "projectnumber", $dbh )
  • unless $form->{projectnumber};
  • $query = qq|
  • UPDATE project
  • SET projectnumber = ?,
  • description = ?,
  • startdate = ?,
  • enddate = ?,
  • parts_id = ?
  • production = ?,
  • customer_id = ?
  • WHERE id = ?|;
  • $sth = $dbh->prepare($query);
  • $sth->execute(
  • $form->{projectnumber}, $form->{description}, $form->{startdate},
  • $form->{enddate}, $form->{id}, $form->{production},
  • $form->{customer_id}, $form->{id}
  • ) || $form->dberror($query);
  • #### add/edit assembly
  • $query = qq|SELECT id FROM parts WHERE id = | . $dbh->quote( $form->{id} );
  • my ($id) = $dbh->selectrow_array($query);
  • if ( !$id ) {
  • $query = qq|
  • INSERT INTO parts (id)
  • VALUES (| . $dbh->quote( $form->{id} ) . qq|)|;
  • $dbh->do($query) || $form->dberror($query);
  • }
  • my $partnumber =
  • ( $form->{partnumber} )
  • ? $form->{partnumber}
  • : $form->{projectnumber};
  • $query = qq|
  • UPDATE parts
  • SET partnumber = ?,
  • description = ?,
  • priceupdate = ?,
  • listprice = ?,
  • sellprice = ?,
  • weight = ?,
  • bin = ?,
  • unit = ?,
  • notes = ?,
  • income_accno_id = (SELECT id FROM chart
  • WHERE accno = ?),
  • partsgroup_id = ?,
  • assembly = '1',
  • obsolete = '1',
  • project_id = ?
  • WHERE id = ?|;
  • $sth = $dbh->prepare($query);
  • $sth->execute(
  • $partnumber,
  • $form->{partdescription},
  • $form->{priceupdate},
  • $form->parse_amount( $myconfig, $form->{listprice} ),
  • $form->parse_amount( $myconfig, $form->{sellprice} ),
  • $form->parse_amount( $myconfig, $form->{weight} ),
  • $form->{bin},
  • $form->{unit},
  • $form->{notes},
  • $income_accno,
  • ($partsgroup_id) ? $partsgroup_id : undef,
  • $form->{id},
  • $form->{id}
  • ) || $form->dberror($query);
  • $query =
  • qq|DELETE FROM partstax WHERE parts_id = | . $dbh->qupte( $form->{id} );
  • $dbh->do($query) || $form->dberror($query);
  • $query = qq|
  • INSERT INTO partstax (parts_id, chart_id)
  • VALUES (?, (SELECT id FROM chart WHERE accno = ?))|;
  • $sth = $dbh->prepare($query);
  • for ( split / /, $form->{taxaccounts} ) {
  • if ( $form->{"IC_tax_$_"} ) {
  • $sth->execute( $form->{id}, $_ )
  • || $form->dberror($query);
  • }
  • }
  • $dbh->commit;
  • }
  • sub stock_assembly {
  • my ( $self, $myconfig, $form ) = @_;
  • my $dbh = $form->{dbh};
  • my $ref;
  • my $query = qq|SELECT * FROM project WHERE id = ?|;
  • my $sth = $dbh->prepare($query) || $form->dberror($query);
  • $query = qq|SELECT COUNT(*) FROM parts WHERE project_id = ?|;
  • my $rvh = $dbh->prepare($query) || $form->dberror($query);
  • if ( !$form->{stockingdate} ) {
  • $query = qq|SELECT current_date|;
  • ( $form->{stockingdate} ) = $dbh->selectrow_array($query);
  • }
  • $query = qq|SELECT * FROM parts WHERE id = ?|;
  • my $pth = $dbh->prepare($query) || $form->dberror($query);
  • $query = qq|
  • SELECT j.*, p.lastcost FROM jcitems j
  • JOIN parts p ON (p.id = j.parts_id)
  • WHERE j.project_id = ?
  • AND j.checkedin <= | . $dbh->quote( $form->{stockingdate} ) . qq|
  • ORDER BY parts_id|;
  • my $jth = $dbh->prepare($query) || $form->dberror($query);
  • $query = qq|
  • INSERT INTO assembly (id, parts_id, qty, bom, adj)
  • VALUES (?, ?, ?, '0', '0')|;
  • my $ath = $dbh->prepare($query) || $form->dberror($query);
  • my $i = 0;
  • my $sold;
  • my $ship;
  • while (1) {
  • $i++;
  • last unless $form->{"id_$i"};
  • $stock = $form->parse_amount( $myconfig, $form->{"stock_$i"} );
  • if ($stock) {
  • $sth->execute( $form->{"id_$i"} );
  • $ref = $sth->fetchrow_hashref(NAME_lc);
  • if ( $stock > ( $ref->{production} - $ref->{completed} ) ) {
  • $stock = $ref->{production} - $ref->{completed};
  • }
  • if ( ( $stock * -1 ) > $ref->{completed} ) {
  • $stock = $ref->{completed} * -1;
  • }
  • $pth->execute( $form->{"id_$i"} );
  • $pref = $pth->fetchrow_hashref(NAME_lc);