EBernhardson has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/295021

Change subject: Add phan and cleanup some found warnings
......................................................................

Add phan and cleanup some found warnings

This still ends up complaining a bunch about OAuthProvider and
RelevanceScoringProvider. Unfortunately because of how the Pimple DI
container works it's not really possible to fix these without throwing a
bunch of supress annotations arround.  Annoyingly there is also the
problem that phan @suppress annotations only work on the closest
function definition, which means each service would have to be marked
with the annotations which is just too verbose. For the moment they are
just throwing errors.

Change-Id: Ic16905576311717ff957f5e3c62c02e240778304
---
A scripts/postprocess-phan.php
A scripts/run-phan.sh
M src/OAuth/MediaWiki.php
M src/RelevanceScoring/Assert/MinimumSubmittedValidator.php
M src/RelevanceScoring/Console/CacheClear.php
M src/RelevanceScoring/Controller/QueriesController.php
M src/RelevanceScoring/Import/Importer.php
M src/RelevanceScoring/RelevanceScoringProvider.php
M src/RelevanceScoring/Repository/QueriesRepository.php
M src/RelevanceScoring/Repository/ResultsRepository.php
M src/RelevanceScoring/Repository/ScoresRepository.php
M src/RelevanceScoring/Repository/ScoringQueueRepository.php
12 files changed, 160 insertions(+), 16 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/wikimedia/discovery/discernatron 
refs/changes/21/295021/1

diff --git a/scripts/postprocess-phan.php b/scripts/postprocess-phan.php
new file mode 100644
index 0000000..e11cd25
--- /dev/null
+++ b/scripts/postprocess-phan.php
@@ -0,0 +1,29 @@
+<?php
+
+$results = file( "php://stdin" );
+foreach ( $results as $error ) {
+       if ( !preg_match( '/^(.*):(\d+) (Phan\w+) (.*)$/', $error, $matches ) ) 
{
+               echo "Failed to parse line: $error\n";
+               continue;
+       }
+       list( $source, $file, $lineno, $type, $message ) = $matches;
+       $errors[$file][] = array(
+               'orig' => $error,
+               // convert from 1 indexed to 0 indexed
+               'lineno' => $lineno - 1,
+               'type' => $type,
+       );
+}
+
+foreach ( $errors as $file => $errors ) {
+       $source = file( $file );
+       foreach ( $errors as $error ) {
+               if ( $error['lineno'] === 0 || !preg_match(
+                       "|/\* @suppress {$error["type"]} |",
+                       $source[$error['lineno'] - 1]
+               ) ) {
+                       echo $error['orig'];
+               }
+       }
+}
+
diff --git a/scripts/run-phan.sh b/scripts/run-phan.sh
new file mode 100755
index 0000000..9220b15
--- /dev/null
+++ b/scripts/run-phan.sh
@@ -0,0 +1,86 @@
+#!/bin/bash
+
+# Some systems, like mediawiki-vagrant, don't have realpath
+if ! which realpath > /dev/null; then
+       realpath() {
+               php -r "echo realpath('$*');"
+       }
+fi
+
+PROJECT_ROOT=$(realpath "${PROJECT_ROOT:-$(dirname "$0")/..}")
+PROJECT="src/" # tests/
+DEPS="vendor/"
+
+set -e
+
+if [ ! -f "$PROJECT_ROOT/app.php" ]; then
+       echo "Could not find installation at $PROJECT_ROOT"
+       echo "Please specify with PROJECT_ROOT environment variable"
+       echo
+       exit 1
+fi
+
+if ! which docker > /dev/null; then
+       echo "Docker not installed. Press any key to install docker or Ctrl-C 
to quit"
+       read -n 1
+       sudo apt-get -y install docker.io 
+       if [ -d /vagrant ]; then
+               # May also be required elsewhere..but not comfortable just 
installing
+               # cgroup-lite to random peoples machines.
+               sudo apt-get -y install cgroup-lite
+       fi
+fi
+
+if ! id -Gn | grep docker > /dev/null; then
+       sudo adduser $(id -un) docker
+       echo "User added to docker group. You need to log out and log back in 
to continue."
+       echo
+       exit 1
+fi
+
+if ! docker images | grep cloudflare/phan > /dev/null; then
+       git clone https://github.com/cloudflare/docker-phan.git 
/tmp/docker-phan.$$
+       pushd /tmp/docker-phan.$$
+       ./build
+       popd
+       # Once build we can safely remove this repo
+       rm -rf /tmp/docker-phan.$$
+fi
+
+for i in $PROJECT; do
+  ALL_DIRS="$ALL_DIRS $PROJECT_ROOT/$i"
+done
+for i in $DEPS; do
+  SKIP_ANALYSIS="$SKIP_ANALYSIS,/mnt/src/$i"
+  ALL_DIRS="$ALL_DIRS $PROJECT_ROOT/$i"
+done
+# Strip leading comma
+SKIP_ANALYSIS="${SKIP_ANALYSIS:1}"
+
+PHAN_IN=$PROJECT_ROOT/phan.in.$$
+SED_PATTERN=$(echo $PROJECT_ROOT | sed 's/[\/&]/\\&/g')
+find $ALL_DIRS -iname '*.php' | sed "s/${SED_PATTERN}/\/mnt\/src/" > $PHAN_IN
+
+docker run \
+       --volume="$PROJECT_ROOT:/mnt/src" \
+       --rm \
+       --user "$(id -u):$(id -g)" \
+       cloudflare/phan:latest \
+       --file-list "/mnt/src/phan.in.$$" \
+       --exclude-directory-list "$SKIP_ANALYSIS" \
+       --output "php://stdout" \
+       | sed "s/\/mnt\/src/$SED_PATTERN/" \
+       | php $(dirname $0)/postprocess-phan.php \
+       | sed "s/$SED_PATTERN//" \
+       > /tmp/phan.out
+
+
+RETVAL=0
+if [ "$(wc -l < /tmp/phan.out)" -ne 0 ]; then
+       RETVAL=1
+fi
+
+cat /tmp/phan.out
+rm "$PHAN_IN" /tmp/phan.out
+exit $RETVAL
+
diff --git a/src/OAuth/MediaWiki.php b/src/OAuth/MediaWiki.php
index b916b26..6bc50fb 100644
--- a/src/OAuth/MediaWiki.php
+++ b/src/OAuth/MediaWiki.php
@@ -73,6 +73,11 @@
         return $data->username;
     }
 
+    /**
+     * @param string $body
+     *
+     * @return TokenCredentials
+     */
     protected function createTokenCredentials($body)
     {
         parse_str($body, $data);
@@ -136,6 +141,7 @@
             $this->cachedUserDetailsResponse = $decoded;
         }
 
+        /* @suppress PhanTypeMismatchReturn parent class annotates this as 
unknown, but we know better */
         return $this->cachedUserDetailsResponse;
     }
 }
diff --git a/src/RelevanceScoring/Assert/MinimumSubmittedValidator.php 
b/src/RelevanceScoring/Assert/MinimumSubmittedValidator.php
index 1a22640..6872f39 100644
--- a/src/RelevanceScoring/Assert/MinimumSubmittedValidator.php
+++ b/src/RelevanceScoring/Assert/MinimumSubmittedValidator.php
@@ -4,6 +4,7 @@
 
 use Symfony\Component\Validator\Constraint;
 use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
 
 class MinimumSubmittedValidator extends ConstraintValidator
 {
@@ -14,6 +15,7 @@
         }
 
         $have = count(array_filter($values, function ($val) { return $val !== 
null; }));
+        /* @suppress PhanUndeclaredMethod Phan doesn't know this is a 
MinimumSubmitted instance */
         $allowed = $constraint->getMinimumAllowed(count($values));
 
         if ($have < $allowed) {
diff --git a/src/RelevanceScoring/Console/CacheClear.php 
b/src/RelevanceScoring/Console/CacheClear.php
index 6b641ab..20ecf3d 100644
--- a/src/RelevanceScoring/Console/CacheClear.php
+++ b/src/RelevanceScoring/Console/CacheClear.php
@@ -3,19 +3,23 @@
 namespace WikiMedia\RelevanceScoring\Console;
 
 use Knp\Command\Command;
+use RecursiveDirectoryIterator;
+use RecursiveIteratorIterator;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Output\OutputInterface;
-use Twig_Environment;
 
 class CacheClear extends Command
 {
-    /** @var Twig_Environment */
-    private $twig;
+    /** @var string */
+    private $cacheDir;
 
-    public function __construct(Twig_Environment $twig)
+    /**
+     * @param string $cacheDir
+     */
+    public function __construct($cacheDir)
     {
         parent::__construct('cache:clear');
-        $this->twig = $twig;
+        $this->cacheDir = $cacheDir;
     }
 
     protected function configure()
@@ -25,8 +29,16 @@
 
     protected function execute(InputInterface $input, OutputInterface $output)
     {
-        $this->twig->clearCacheFiles();
-        $output->writeln('Cache cleared');
+        $it = new RecursiveDirectoryIterator(
+            $this->cacheDir,
+            RecursiveIteratorIterator::LEAVES_ONLY
+        );
+        $it = new RecursiveIteratorIterator($it);
+        foreach ($it as $file) {
+            if ($file->isFile()) {
+                @unlink($file->getPathname());
+            }
+        }
 
         return 0;
     }
diff --git a/src/RelevanceScoring/Controller/QueriesController.php 
b/src/RelevanceScoring/Controller/QueriesController.php
index fc37cc0..80b6f96 100644
--- a/src/RelevanceScoring/Controller/QueriesController.php
+++ b/src/RelevanceScoring/Controller/QueriesController.php
@@ -29,6 +29,8 @@
     private $resultsRepo;
     /** @var ScoresRepository */
     private $scoresRepo;
+    /** @var ScoringQueueRepository */
+    private $scoringQueueRepo;
     /** @var string[] */
     private $wikis;
 
diff --git a/src/RelevanceScoring/Import/Importer.php 
b/src/RelevanceScoring/Import/Importer.php
index 3b1ba79..331d475 100644
--- a/src/RelevanceScoring/Import/Importer.php
+++ b/src/RelevanceScoring/Import/Importer.php
@@ -38,7 +38,7 @@
         $this->scoringQueueRepo = $scoringQueueRepo;
         $this->wikis = $wikis;
         $this->getters = $getters;
-        $this->output = function () {};
+        $this->output = function ($line) {};
     }
 
     public function setOutput($callable)
diff --git a/src/RelevanceScoring/RelevanceScoringProvider.php 
b/src/RelevanceScoring/RelevanceScoringProvider.php
index 139fa73..003ad4a 100644
--- a/src/RelevanceScoring/RelevanceScoringProvider.php
+++ b/src/RelevanceScoring/RelevanceScoringProvider.php
@@ -191,7 +191,9 @@
     private function registerConsole(Application $app)
     {
         $app['search.console.cache-clear'] = function () use ($app) {
-            return new CacheClear($app['twig']);
+            $options = $app['twig.options'];
+
+            return new CacheClear($options['cache']);
         };
 
         $app['search.console.import'] = function () use ($app) {
diff --git a/src/RelevanceScoring/Repository/QueriesRepository.php 
b/src/RelevanceScoring/Repository/QueriesRepository.php
index 6cd00ba..462e812 100644
--- a/src/RelevanceScoring/Repository/QueriesRepository.php
+++ b/src/RelevanceScoring/Repository/QueriesRepository.php
@@ -44,10 +44,11 @@
             return new None();
         }
 
-        $rand = mt_rand(0, $maxId);
+        $rand = mt_rand(0, (int) $maxId);
         $qb = $this->db->createQueryBuilder()
             ->select('q.id')
             ->from('queries', 'q')
+            /* @suppress PhanTypeMismatchArgument DBAL is mis-annotated to 
only take strings here */
             ->add('join', [
                 'q' => [
                     [
@@ -194,14 +195,14 @@
      * @param string $wiki
      * @param string $wiki
      * @param string $query
-     * @param bool   $imported
+     * @param string $imported Set to 'imported' to mark as already imported
      *
      * @return int
      *
      * @throws DuplicateQueryException
      * @throws RuntimeException
      */
-    public function createQuery(User $user, $wiki, $query, $imported = false)
+    public function createQuery(User $user, $wiki, $query, $imported = '')
     {
         try {
             $inserted = $this->db->insert('queries', [
@@ -219,7 +220,7 @@
             throw new RuntimeException('Failed insert new query');
         }
 
-        return $this->db->lastInsertId();
+        return (int) $this->db->lastInsertId();
     }
 
     /**
@@ -267,10 +268,12 @@
         if ($userId !== null) {
             $sql .= ' AND user_id = ?';
             $params[] = $userId;
+            /* @suppress PhanUndeclaredClassConstant phan is missing this 
constant */
             $types[] = PDO::PARAM_INT;
         }
         $sql .= ' LIMIT ?';
         $params[] = $limit;
+        /* @suppress PhanUndeclaredClassConstant phan is missing this constant 
*/
         $types[] = PDO::PARAM_INT;
 
         return $this->db->fetchAll($sql, $params, $types);
diff --git a/src/RelevanceScoring/Repository/ResultsRepository.php 
b/src/RelevanceScoring/Repository/ResultsRepository.php
index 6d0f6d5..e4a8a27 100644
--- a/src/RelevanceScoring/Repository/ResultsRepository.php
+++ b/src/RelevanceScoring/Repository/ResultsRepository.php
@@ -46,7 +46,7 @@
             return new None();
         }
 
-        $rand = mt_rand(0, $maxId);
+        $rand = mt_rand(0, (int) $maxId);
         $sql = <<<EOD
 SELECT r.id
   FROM results r
diff --git a/src/RelevanceScoring/Repository/ScoresRepository.php 
b/src/RelevanceScoring/Repository/ScoresRepository.php
index 7440f2a..3494239 100644
--- a/src/RelevanceScoring/Repository/ScoresRepository.php
+++ b/src/RelevanceScoring/Repository/ScoresRepository.php
@@ -40,7 +40,7 @@
             throw new RuntimeException('Failed inserting row');
         }
 
-        return $this->db->lastInsertId();
+        return (int) $this->db->lastInsertId();
     }
 
     public function getNumberOfScores(array $queryIds)
diff --git a/src/RelevanceScoring/Repository/ScoringQueueRepository.php 
b/src/RelevanceScoring/Repository/ScoringQueueRepository.php
index 723edf0..7ab4553 100644
--- a/src/RelevanceScoring/Repository/ScoringQueueRepository.php
+++ b/src/RelevanceScoring/Repository/ScoringQueueRepository.php
@@ -136,6 +136,7 @@
             }
         });
 
+        /* @suppress PhanUndeclaredVariable Phan doesn't recognize this as 
being defined above */
         return $res;
     }
 
@@ -151,8 +152,9 @@
         $rowsDeleted = $this->db->delete('scoring_queue', $conditions);
 
         if ($rowsDeleted > 1) {
-            $this->logger->warn(
+            $this->logger->warning(
                 'Unexpectedly deleted {numRows} for query {query_id} and user 
{user_id}',
+                /* @suppress PhanTypeMismatchArgument Phan doesn't understand 
array addition */
                 $conditions + ['numRows' => $rowsDeleted]
             );
         } elseif ($rowsDeleted === 0) {

-- 
To view, visit https://gerrit.wikimedia.org/r/295021
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic16905576311717ff957f5e3c62c02e240778304
Gerrit-PatchSet: 1
Gerrit-Project: wikimedia/discovery/discernatron
Gerrit-Branch: master
Gerrit-Owner: EBernhardson <ebernhard...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to