public static function cleanModuleList($modules)
    {
        $app = \JFactory::getApplication();

        // Apply negative selections and eliminate duplicates
        $Itemid = \JFactory::getApplication()->input->getInt('Itemid');
        $negId = $Itemid ? -(int) $Itemid : false;
        $clean = array();
        $dupes = array();

        foreach ($modules as $i => $module)
        {
            // The module is excluded if there is an explicit prohibition
            $negHit = ($negId === (int) $module->menuid);

            if (isset($dupes[$module->id]))
            {
                // If this item has been excluded, keep the duplicate flag set,
                // but remove any item from the modules array.
                if ($negHit)
                {
                    unset($clean[$module->id]);
                }

                continue;
            }

            $dupes[$module->id] = true;

            // Only accept modules without explicit exclusions.
            if ($negHit)
            {
                continue;
            }

            $module->name = substr($module->module, 4);
            $module->style = null;
            $module->position = strtolower($module->position);

            $clean[$module->id] = $module;
        }

        unset($dupes);

        // Do 3rd party stuff to manipulate module array.
        // Any plugins using this architecture may make alterations to the referenced $modules array.
        // To remove items you can do unset($modules[n]) or $modules[n]->published = false.

        // "onPrepareModuleList" may alter or add $modules, and does not need to return anything.
        // This should be used for module addition/deletion that the user would expect to happen at an
        // early stage.
        $app->triggerEvent( 'onPrepareModuleList', array( &$clean ) );

        // "onAlterModuleList" may alter or add $modules, and does not need to return anything.
        $app->triggerEvent( 'onAlterModuleList', array( &$clean ) );

        // "onPostProcessModuleList" allows a plugin to perform actions like parameter changes
        // on the completed list of modules and is guaranteed to occur *after*
        // the earlier plugins.
        $app->triggerEvent( 'onPostProcessModuleList', array( &$clean ) );

        // Remove any that were marked as disabled during the preceding steps
        /*foreach ( $clean as $id => $module )
        {
            if ( !isset( $module->published ) || $module->published == 0 )
            {
                unset( $clean[$id] );
            }
        }*/

        // Return to simple indexing that matches the query order.
        return array_values($clean);
    }