View Issue Details

IDProjectCategoryView StatusLast Update
0001784XdebugCode Coveragepublic2020-05-18 14:41
Reporterabhituls55@gmail.com Assigned Toderick  
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionnot fixable 
Product Version2.9.5 
Summary0001784: Values inside the array are being treated as non-executable code.
Description

I am using xdebug with phpunit 7.5. I am getting white-lines (non-executable code) on some lines which are actually executing and should be treated as executable code. All these lines are inside array.
For eg.
155 [
156 'stockareaId.required' => 'Stockarea Id is required required',
157 'product_lots.required' => 'Product Lots is required',
158 'product_lots.array' => 'Product Lots must be array',
159 'product_lots..string' => 'Product Lot number must be an alphanumeric string',
160 'product_lots.
.alpha_num' => 'Product Lot number must be an alphanumeric string',
161 'product_lots..unique' => 'Product Lot number must be unique to the product',
162 'product_lots.
.distinct' => 'Product Lot numbers for the product must be distinct',
163 ]);
164

In this only 156 was coming green. All others are neither red nor green. I am 100% sure other values in array are also getting executed since my test-cases are verifying their outputs and have also used my own debugging. But Xdebug is showing them non-executable code. But firstly they are executable code and secondly they are not getting shown as exectued.

Tagsvisual html
Attached Files
error.PNG (35,694 bytes)   
error.PNG (35,694 bytes)   
Operating Systemwindows 10
PHP Version7.3.5-7.3.9

Activities

derick

2020-05-18 00:08

administrator   ~0005412

It's very likely that PHP has optimised these executable lines away, it's kinda smart like that. Please provide the full PHP file that has this problem as an attachment.

abhituls55@gmail.com

2020-05-18 13:50

reporter   ~0005413

Here is the php file you asked for which contains this code.

ProductController.php (12,018 bytes)   
<?php

namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Requests\Admin\ProductStoreRequest;
use App\Http\Requests\Admin\ProductUpdateRequest;
use App\Models\Product;
use App\Models\ProductLot;
use App\Exceptions\Handler;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
use App\Http\Resources\ProductResource;
use App\Http\Resources\ProductLotResource;
use Illuminate\Support\Facades\Validator;
use App\Rules\ProductLots;
use Illuminate\Validation\Rule;
use Symfony\Component\HttpFoundation\Response;

/**
 * @covers \ProductController
 */
class ProductController extends Controller{

    protected $table = 'products';

    /**
     * Store the product.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(ProductStoreRequest $request){

        $dimensions = array($request->length, $request->breadth,
            $request->height);
        sort($dimensions);
        $weight = $request->weight;

        $size_configuration_id = Product::getSizeConfigurationId($dimensions, $weight);
        // What if there's no such id?

        $metadata = json_encode([
            "created_by" => "admin"
        ],true);

        $stockarea_id = Product::getStockareaId();

        DB::beginTransaction(); //Start db transaction for rollback query when error
        try {
            $product = Product::create([
                'stockarea_id' => $stockarea_id,
                'metadata' => $metadata,
                'size_configuration_id' => $size_configuration_id,
                'length' => $request->length,
                'breadth' => $request->breadth,
                'height' => $request->height,
                'weight' => $request->weight,
                'value' => $request->value,
                'serial_number_scan' => $request->serial_number_scan,
                'sku' => $request->sku,
                'barcode' => $request->barcode,
                'resource_type' => $request->resource_type,
                'resource_id' => $request->resource_id,
                'reorder_point' => $request->reorder_point,
                'virtual_product' => $request->virtual_product,
                'hazardous_product' => $request->hazardous_product,
                'fragile_product' => $request->fragile_product,
                'status' => $request->status,
                'case_product' => $request->case_product,
                'units_in_case' => $request->units_in_case,
                'case_item_id' => $request->case_item_id,
                'lot_product' => $request->lot_product,
                'expiration_date' => $request->expiration_date,
                'description' => $request->description,
                'insured' => $request->insured,
                'packaging_type_id' => $request->packaging_type_id,
                'product_category_id' => $request->product_category_id,
            ]);

            // Add Product Lots
            if($request->lot_product){
                $product_lots = $request->product_lots;
                foreach($product_lots as $lot_number){
                    ProductLot::create([
                        'lot_number' => $lot_number,
                        'product_id' => $product->id,
                    ]);
                }
            }

            DB::commit();
            return new ProductResource($product);
        } catch (\Exception $e) {
            error_log("GAVE ME AN EXCEPTION");
            DB::rollBack();
            return response()->json(['error' => $e], 500);
        }
    }


    /**
     * Get the product with given stoackarea_id.
     *
     * @param int $stockarea_id
     * @return \Illuminate\Http\Response
     */
    public function show($stockarea_id){
        $validator = Validator::make(['stockarea_id' => $stockarea_id],
            [ 'stockarea_id' => ['required'] ],
            ['stockareaId.required' => 'category Stockarea Id is required required']
        );

        if($validator->fails()){
            return response()->json(['errors' => $validator->errors()], 422);
        }

        $product = Product::where('stockarea_id', $stockarea_id)->first();
        return new ProductResource($product);
    }


    /**
     * Get all the products.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(){
        return ProductResource::collection(Product::all());
    }


    /**
     * Store the product lots for the product with the given stockarea_id.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function storeProductLots(Request $request){
        $product = Product::where('stockarea_id', $request->stockarea_id)->first();
        $product_id = $product->id;
        $validator = Validator::make(
            [
                'stockarea_id' => $request->stockarea_id,
                'product_lots' => $request->product_lots,
            ],
            [
                'stockarea_id' => ['required'],
                'product_lots' => ['required','array'],
                'product_lots.*' => ['required', 'string', 'alpha_num', 'distinct',
                    Rule::unique('product_lots', 'lot_number')->where(function ($query) use($product_id) {
                        return $query->where('deleted_at', NULL)
                            ->where('product_id', $product_id);
                    })]
            ],
            [
                'stockareaId.required' => 'Stockarea Id is required required',
                'product_lots.required' => 'Product Lots is required',
                'product_lots.array' => 'Product Lots must be array',
                'product_lots.*.string' => 'Product Lot number must be an alphanumeric string',
                'product_lots.*.alpha_num' => 'Product Lot number must be an alphanumeric string',
                'product_lots.*.unique' => 'Product Lot number must be unique to the product',
                'product_lots.*.distinct' => 'Product Lot numbers for the product must be distinct',
            ]);

        if($validator->fails()){
            return response()->json(['errors' => $validator->errors()], 422);
        }

        $product_lots = $request->product_lots;

        DB::beginTransaction();
        try{
            foreach($product_lots as $lot_number){
                ProductLot::create([
                    'lot_number' => $lot_number,
                    'product_id' => $product->id,
                ]);
            }
            DB::commit();

            return ProductLotResource::collection(
                ProductLot::where('product_id', $product->id)
                ->wherein('lot_number', $product_lots)
                ->get());
        }
        catch(\Exception $e){
            DB::rollBack();
            return response()->json(['error' => $e], 500);
        }
    }


    /**
     * Delete the product with given stockarea_id.
     *
     * @param int $stockarea_id
     * @return \Illuminate\Http\Response
     */
    public function deleteProduct($stockarea_id){
        $validator = Validator::make(['stockarea_id' => $stockarea_id],
            ['stockarea_id' => ['required']],
            ['stockareaId.required' => 'Stockarea Id is required required']
        );

        if($validator->fails()){
            return response()->json(['errors' => $validator->errors()], 422);
        }

        DB::beginTransaction();
        try{
            Product::where('stockarea_id', $stockarea_id)->delete();
            DB::commit();
            return response('Deleted',Response::HTTP_OK);
        }
        catch(\Exception $e){
            DB::rollback();
            throw new \Askedio\SoftCascade\Exceptions\SoftCascadeLogicException($e->getMessage());
        }
    }


    /**
     * Update the product with given stockarea_id.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function update(ProductUpdateRequest $request){
        $product = Product::where('stockarea_id', $request->stockarea_id)->first();
        $product->fill($request->all());

        $dimensions = array($request->length, $request->breadth,
            $request->height);
        sort($dimensions);
        $weight = $request->weight;

        $size_configuration_id = Product::getSizeConfigurationId($dimensions, $weight);

        $product->size_configuration_id = $size_configuration_id;

        $metadata = (array)json_decode($product->metadata);
        // Add the updates field if not already there.
        if(!isset($metadata['updates'])){
            $metadata['updates'] = array();
        }
        // Append to the updates field in the metadata, updated_by and updated_at.
        array_push($metadata['updates'], [
            "updated_by" => "admin",
            "updated_at" => now(),
        ]);

        $product->metadata = json_encode($metadata);
        $product->save();

        // Update product Lots
        if($request->lot_product == TRUE){
            $product_lots = $request->product_lots;
            foreach($product_lots as $product_lot){
                ProductLot::where('id', $product_lot['product_lot_id'])
                    ->update(['lot_number' => $product_lot['lot_number']]);
            }
        }
        return new ProductResource($product);
   }


    /**
     * Delete the product lots for the product with given stockarea_id.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function deleteProductLots(Request $request){
        $product = Product::where('stockarea_id', $request->stockarea_id)->first();
        $product_id = $product->id;

        $validator = Validator::make(
            [
                'stockarea_id' => $request->stockarea_id,
                'product_lots' => $request->product_lots,
            ],
            [
                'stockarea_id' => ['required'] ,
                'product_lots' => ['required','array'],
                'product_lots.*' => ['required', 'string', 'alpha_num', 'distinct',
                    Rule::exists('product_lots', 'lot_number')->where(function ($query) use($product_id) {
                        return $query->where('product_id', $product_id);
                    })]
            ],
            [
                'stockareaId.required' => 'Stockarea Id is required required',
                'product_lots.required' => 'Product Lots is required',
                'product_lots.array' => 'Product Lots must be array',
                'product_lots.*.required' => 'Product lots array must not be empty.',
                'product_lots.*.string' => 'Product Lot number must be an alphanumeric string',
                'product_lots.*.alpha_num' => 'Product Lot number must be an alphanumeric string',
                'product_lots.*.exists' => 'The product lot numbers must exist for the product',
                'product_lots.*.distinct' => 'The product lot numbers for the product must be distinct',
            ]
        );

        if($validator->fails()){
            return response()->json(['errors' => $validator->errors()], 422);
        }
        $product_lots = $request->product_lots;

        DB::beginTransaction();
        try{
            ProductLot::where('product_id', $product_id)
                ->wherein('lot_number', $product_lots)
                ->delete();
            DB::commit();
            return response('Deleted',Response::HTTP_OK);
        }
        catch(\Exception $e){
            DB::rollBack();
            return response()->json(['error' => $e], 500);
        }
   }
}
ProductController.php (12,018 bytes)   

derick

2020-05-18 14:17

administrator   ~0005414

Last edited: 2020-05-18 14:17

PHP's Engine has generated the following internal code for this:

<pre>
147 27 INIT_ARRAY 0000015:0000007 <array>, 'stockarea_id'
28 ADD_ARRAY_ELEMENT 0000015:0000007 <array>, 'product_lots'
</pre>

Although it has created the array with the first element correctly on line 147, it also did the addition of the second array element on that same line, and not on line 148.

<pre>
149 29 INIT_ARRAY 0000017:0000008 'required'
30 ADD_ARRAY_ELEMENT 0000017:0000008 'string'
31 ADD_ARRAY_ELEMENT 0000017:0000008 'alpha_num'
32 ADD_ARRAY_ELEMENT 0000017:0000008 'distinct'
150 33 INIT_STATIC_METHOD_CALL 'Illuminate%5CValidation%5CRule', 'unique'
34 EXT_FCALL_BEGIN
35 SEND_VAL_EX 'product_lots'
36 SEND_VAL_EX 'lot_number'
37 DO_FCALL 0 $9
38 EXT_FCALL_END
39 INIT_METHOD_CALL $9, 'where'
40 EXT_FCALL_BEGIN
41 DECLARE_LAMBDA_FUNCTION '%00app%5Chttp%5Ccontrollers%5Cadmin%5C%7Bclosure%7D%2Ftmp%2FProductController.php0x7fb0d95af5ec'
42 BIND_LEXICAL 0000015:0000009, !2
</pre>
I don't quite understand why line 150 isn't in your coverage output, I think it should show up. However, I can't really run this code, so I can not investigate that now. If you'd like me to find out, please submit a new bug report that I can run locally—preferably as short as possible as is described in the documentation (https://xdebug.org/reporting-bugs).
<pre>
153 43 SEND_VAL_EX 0000015:0000009
44 DO_FCALL 0 $9
45 EXT_FCALL_END
46 ADD_ARRAY_ELEMENT 0000017:0000008 $9
47 ADD_ARRAY_ELEMENT 0000015:0000007 0000017:0000008, 'product_lots.%2A'
48 SEND_VAL_EX 0000015:0000007
</pre>
The above adds the result of the Rule::unique call to the array.
<pre>
156 49 SEND_VAL_EX <array>
50 DO_FCALL 0 $7
51 EXT_FCALL_END
52 ASSIGN !3, $7
</pre>
PHP has indeed optimised the whole array creation from line 156 to 162 into one line as I expected. This makes it look like PHP didn't execute the code, but it was just clever and optimised this into a constant array (SEND_VAL_EX <array> gives that away). I can't do anything about this on the Xdebug side of things.
<pre>
165 53 EXT_STMT
54 INIT_METHOD_CALL !3, 'fails'
55 EXT_FCALL_BEGIN
56 DO_FCALL 0 $7
57 EXT_FCALL_END
58 > JMPZ $7, ->76
</pre>
This then calls the 'fails()' method on line 165.

abhituls55@gmail.com

2020-05-18 14:41

reporter   ~0005415

Thanks derick for your help and information. I can't product a reduced test, as it would take sufficient time for me to generate it and for you to go through it as these test cases are bonded with phpunit inside laravel framework. But still I got the idea where the problem can be. Thanks for help.

Issue History

Date Modified Username Field Change
2020-05-17 23:36 abhituls55@gmail.com New Issue
2020-05-17 23:36 abhituls55@gmail.com Tag Attached: visual html
2020-05-17 23:36 abhituls55@gmail.com File Added: error.PNG
2020-05-18 00:08 derick Assigned To => derick
2020-05-18 00:08 derick Status new => feedback
2020-05-18 00:08 derick Note Added: 0005412
2020-05-18 13:50 abhituls55@gmail.com File Added: ProductController.php
2020-05-18 13:50 abhituls55@gmail.com Note Added: 0005413
2020-05-18 13:50 abhituls55@gmail.com Status feedback => assigned
2020-05-18 14:17 derick Status assigned => resolved
2020-05-18 14:17 derick Resolution open => not fixable
2020-05-18 14:17 derick Note Added: 0005414
2020-05-18 14:17 derick Note Edited: 0005414
2020-05-18 14:41 abhituls55@gmail.com Note Added: 0005415