package WebGUI::Operation::SpellCheck; #------------------------------------------------------------------- # WebGUI is Copyright 2001-2009 Plain Black Corporation. #------------------------------------------------------------------- # Please read the legal notices (docs/legal.txt) and the license # (docs/license.txt) that came with this distribution before using # this software. #------------------------------------------------------------------- # http://www.plainblack.com info@plainblack.com #------------------------------------------------------------------- use strict; use WebGUI::Utility; use File::Path qw(mkpath); # Optional, but if unavailable, spell checking will have no effect. my $spellerAvailable; BEGIN { eval { require Text::Aspell; }; $spellerAvailable = 1 unless $@; }; =head1 NAME Package WebGUI::Operation::SpellCheck =head1 DESCRIPTION Operation for server side spellchecking functions. =cut #------------------------------------------------------------------- =head2 _getSpeller ( session , language ) Returns an instanciated Text::Aspell object. =head3 session An instanciated session object. =head3 language The language code to use for spell checking. =cut sub _getSpeller { my $session = shift; my $lang = shift; die "Server side spellcheck not available\n" unless $spellerAvailable; # Get language my $speller = Text::Aspell->new; die "Language not available in server side spellcheck" unless (isIn($lang, map {m/^.*?:([^:]*):.*?$/} $speller->list_dictionaries)); # User homedir my $homeDir = $session->config->get('uploadsPath').'/dictionaries/'; my $userId = $session->user->userId; if (length($userId) < 22) { $homeDir .= "oldIds/$userId"; } else { $userId =~ m/^(.{2})(.{2})/; $homeDir .= "$1/$2/$userId"; } mkpath($homeDir) unless (-e $homeDir); # Set speller options. $speller->set_option('home-dir', $homeDir); $speller->set_option('lang', $lang); return $speller; } #------------------------------------------------------------------- =head2 addWord ( $session, $language, $word ) Adds a word sent by the tinymce spellchecker plugin to the personal dictionary of the the current user. =head3 $session The instanciated session object =head3 $language The dictionary language to use. =head3 $word The word to add to the dictionary. =cut sub addWord { my $session = shift; my $language = shift; my $word = shift; die "You must be logged in to add words to your dictionary.\n:" if ($session->user->isVisitor); my $speller = _getSpeller($session, $language); $speller->add_to_personal($word); $speller->save_all_word_lists; return 1; } #------------------------------------------------------------------- =head2 checkWords ( $session, $language, \@words ) Check the spelling on a list of words and returns a list of misspelled words as an array reference =head3 $session The instanciated session object =head3 $language The dictionary language to use. =head3 \@word The words to check the spelling of as an array reference. =cut sub checkWords { my $session = shift; my $language = shift; my $words = shift; my $speller = _getSpeller($session, $language); my @result; foreach my $word (@$words) { unless ($speller->check($word)) { push(@result, $word); } } return \@result; } #------------------------------------------------------------------- =head2 getSuggestions ( $session, $language, $word ) Returns a list of suggested words for a misspelled word sent by the tinyMCE spellchecker as an array reference. =head3 $session The instanciated session object. =head3 $language The dictionary language to use. =head3 $word The misspelled word to get suggestions for. =cut sub getSuggestions { my $session = shift; my $language = shift; my $word = shift; my $speller = _getSpeller($session, $language); my @result = $speller->suggest($word); return \@result; } #------------------------------------------------------------------- =head2 www_spellCheck ( session ) Fetches the JSON data sent by the TinyMCE spell checker and dispatches to the correct sub to handle each request type. Encodes the result as a JSON string to be sent back to the client. =head3 session The instanciated session object. =cut sub www_spellCheck { my $session = shift; # JSON data is sent directly as POST data, read it into a scalar then decode my $data = ''; while ($session->request->read(my $buffer, 1024)) { $data .= $buffer; } # work around TinyMCE JSON encoding bug $data =~ s/([^\\](?:\\\\)*)\\'/$1'/g; my $params = JSON->new->decode($data); my $result; # dispatch to different subs based on the 'method' in the JSON data my %dispatch = ( checkWords => \&checkWords, getSuggestions => \&getSuggestions, addWord => \&addWord, ); if (exists $dispatch{$params->{method}}) { eval { # get results from sub and build result data $result = { result => $dispatch{$params->{method}}->($session, @{ $params->{params} }) }; }; if ($@) { $result = {error => {errstr => $@}}; } } else { $result = {error => {errstr => "Invalid request"}}; } # add request id and send to client as JSON blob $result->{id} = $params->{id}; $session->http->setMimeType("text/plain; charset=utf-8"); return JSON->new->encode($result); } 1;