问:
Python Optimized Comparison Between List of Dict
I'm trying to see whether nodes reside within the volume of a sphere, and add the node id to a list. However, the efficiency of the algorithm is incredibly slow and I'm not sure how to improve it.

I have two lists. List A has the format [{'num': ID, 'x': VALUE, 'y': VALUE, 'z': VALUE] while List B has the format [{'x': VALUE, 'y': VALUE, 'z': VALUE, 'rad': VALUE}].

The size of both lists can run upwards of 100,000 items each.

My current code is posted below, but it's very inefficient.

```<code>    filteredList = []
    for i in range(len(sList)):

            minx = (sList[i]['x']) - (sList[i]['radius'])
            maxx = (sList[i]['x']) + (sList[i]['radius'])
            miny = (sList[i]['y']) - (sList[i]['radius'])
            maxy = (sList[i]['y']) + (sList[i]['radius'])
            minz = (sList[i]['z']) - (sList[i]['radius'])
            maxz = (sList[i]['z']) + (sList[i]['radius'])

            for j in range(len(nList)):
                    if minx <= nList[j]['x'] <= maxx:
                            if miny <= nList[j]['y'] <= maxy:
                                    if minz <= nList[j]['z'] <= maxz:
                                            tmpRad = findRadius(sList[i],nList[j])
                                            if tmpRad <= sList[i]['radius']:
                                                    filteredList.append(int(nList[j]['num']))
</code>```

I'm at a loss and appreciate any ideas.

Edit: Adding extra information about the data format.

List A (nList) -- defines nodes, with locations x,y,z, and identifier num

[{'y': 0.0, 'x': 0.0, 'num': 1.0, 'z': 0.0},

{'y': 0.0, 'x': 1.0, 'num': 2.0, 'z': 0.0},

{'y': 0.0, 'x': 2.0, 'num': 3.0, 'z': 0.0},

{'y': 0.0, 'x': 3.0, 'num': 4.0, 'z': 0.0},

{'y': 0.0, 'x': 4.0, 'num': 5.0, 'z': 0.0},

{'y': 0.0, 'x': 5.0, 'num': 6.0, 'z': 0.0},

{'y': 0.0, 'x': 6.0, 'num': 7.0, 'z': 0.0},

{'y': 0.0, 'x': 7.0, 'num': 8.0, 'z': 0.0},

{'y': 0.0, 'x': 8.0, 'num': 9.0, 'z': 0.0},

{'y': 0.0, 'x': 9.0, 'num': 10.0, 'z': 0.0}]

List B (sList) -- defines spheres using x,y,z, radius

[{'y': 18.0, 'x': 25.0, 'z': 26.0, 'radius': 0.0056470000000000001},

{'y': 29.0, 'x': 23.0, 'z': 45.0, 'radius': 0.0066280000000000002},

{'y': 46.0, 'x': 29.0, 'z': 13.0, 'radius': 0.014350999999999999},

{'y': 0.0, 'x': 20.0, 'z': 25.0, 'radius': 0.014866000000000001},

{'y': 27.0, 'x': 31.0, 'z': 18.0, 'radius': 0.018311999999999998},

{'y': 10.0, 'x': 36.0, 'z': 46.0, 'radius': 0.024702000000000002},

{'y': 27.0, 'x': 13.0, 'z': 48.0, 'radius': 0.027300999999999999},

{'y': 14.0, 'x': 1.0, 'z': 13.0, 'radius': 0.033889000000000002},

{'y': 31.0, 'x': 20.0, 'z': 11.0, 'radius': 0.034118999999999997},

{'y': 23.0, 'x': 28.0, 'z': 8.0, 'radius': 0.036683}]

答:
First off, Python isn't built for that kind of iteration. Using indices to get at each element of a list is backwards, a kind of brain-damage that's taught by low-level languages where it's faster. In Python it's actually slower. range(len(whatever)) actually creates a new list of numbers, and then you work with the numbers that are handed to you from that list. What you really want to do is just work with objects that are handed to you from whatever.

While we're at it, we can pull out the common s['radius'] bit that is checked several times, and put all the if-checks for the bounding box on one line. Oh, and we don't need a separate 'tmpRad', and I assume the 'num's are already ints and don't need to be converted (if they do, why? Why not just have them converted ahead of time?)

None of this will make a huge difference, but it at least makes it easier to read, and definitely doesn't hurt.

```<code>filteredList = []
for s in sList:
  radius = s['radius']
  minx = s['x'] - radius
  maxx = s['x'] + radius
  miny = s['y'] - radius
  maxy = s['y'] + radius
  minz = s['z'] - radius
  maxz = s['z'] + radius

  for n in nList:
    if (minx <= n['x'] <= maxx) and (miny <= n['y'] <= maxy) and \
       (minz <= n['z'] <= maxz) and (findRadius(s, n) <= radius):
      filteredList.append(n['num'])
</code>```

Now it's at least clear what's going on.

However, for the scale of the problem we're working with, it sounds like we're going to need algorithmic improvements. What you probably want to do here is use some kind of BSP (binary space partitioning) technique. The way this works is:

First, we rearrange the nList into a tree. We cut it up into 8 smaller lists, based on whether x > 0, whether y > 0 and whether z > 0 for each point (8 combinations of the 3 boolean results). Then each of those gets cut into 8 again, using the same sort of criteria - e.g. if the possible range for x/y/z is -10..10, then we cut the "x > 0, y > 0, z > 0" list up according to whether x > 5, y > 5, z > 5, etc. You get the idea.

For each point in the sList, we check whether minx > 0, etc. The beautiful part: if minx > 0, we don't have to check any of the 'x < 0' lists, and if maxx < 0, we don't have to check any of the 'x > 0' lists. And so forth. We figure out which of the 8 "octants" of the space the bounding box intersects with; and for each of those, we recursively check the appropriate octants of those octants, etc. until we get to the leaves of the tree, and then we do the normal point-in-bounding-box, then point-in-sphere tests.

Body:
I'm trying to see whether nodes reside within the volume of a sphere, and add the node id to a list. However, the efficiency of the algorithm is incredibly slow and I'm not sure how to improve it.

I have two lists. List A has the format [{'num': ID, 'x': VALUE, 'y': VALUE, 'z': VALUE] while List B has the format [{'x': VALUE, 'y': VALUE, 'z': VALUE, 'rad': VALUE}].

The size of both lists can run upwards of 100,000 items each.

My current code is posted below, but it's very inefficient.

    filteredList = []
    for i in range(len(sList)):

            minx = (sList[i]['x']) - (sList[i]['radius'])
            maxx = (sList[i]['x']) + (sList[i]['radius'])
            miny = (sList[i]['y']) - (sList[i]['radius'])
            maxy = (sList[i]['y']) + (sList[i]['radius'])
            minz = (sList[i]['z']) - (sList[i]['radius'])
            maxz = (sList[i]['z']) + (sList[i]['radius'])

            for j in range(len(nList)):
                    if minx <= nList[j]['x'] <= maxx:
                            if miny <= nList[j]['y'] <= maxy:
                                    if minz <= nList[j]['z'] <= maxz:
                                            tmpRad = findRadius(sList[i],nList[j])
                                            if tmpRad <= sList[i]['radius']:
                                                    filteredList.append(int(nList[j]['num']))

I'm at a loss and appreciate any ideas.

Edit: Adding extra information about the data format.

List A (nList) -- defines nodes, with locations x,y,z, and identifier num

[{'y': 0.0, 'x': 0.0, 'num': 1.0, 'z': 0.0},

{'y': 0.0, 'x': 1.0, 'num': 2.0, 'z': 0.0},

{'y': 0.0, 'x': 2.0, 'num': 3.0, 'z': 0.0},

{'y': 0.0, 'x': 3.0, 'num': 4.0, 'z': 0.0},

{'y': 0.0, 'x': 4.0, 'num': 5.0, 'z': 0.0},

{'y': 0.0, 'x': 5.0, 'num': 6.0, 'z': 0.0},

{'y': 0.0, 'x': 6.0, 'num': 7.0, 'z': 0.0},

{'y': 0.0, 'x': 7.0, 'num': 8.0, 'z': 0.0},

{'y': 0.0, 'x': 8.0, 'num': 9.0, 'z': 0.0},

{'y': 0.0, 'x': 9.0, 'num': 10.0, 'z': 0.0}]

List B (sList) -- defines spheres using x,y,z, radius

[{'y': 18.0, 'x': 25.0, 'z': 26.0, 'radius': 0.0056470000000000001},

{'y': 29.0, 'x': 23.0, 'z': 45.0, 'radius': 0.0066280000000000002},

{'y': 46.0, 'x': 29.0, 'z': 13.0, 'radius': 0.014350999999999999},

{'y': 0.0, 'x': 20.0, 'z': 25.0, 'radius': 0.014866000000000001},

{'y': 27.0, 'x': 31.0, 'z': 18.0, 'radius': 0.018311999999999998},

{'y': 10.0, 'x': 36.0, 'z': 46.0, 'radius': 0.024702000000000002},

{'y': 27.0, 'x': 13.0, 'z': 48.0, 'radius': 0.027300999999999999},

{'y': 14.0, 'x': 1.0, 'z': 13.0, 'radius': 0.033889000000000002},

{'y': 31.0, 'x': 20.0, 'z': 11.0, 'radius': 0.034118999999999997},

{'y': 23.0, 'x': 28.0, 'z': 8.0, 'radius': 0.036683}]

Body:
First off, Python isn't built for that kind of iteration. Using indices to get at each element of a list is backwards, a kind of brain-damage that's taught by low-level languages where it's faster. In Python it's actually slower. range(len(whatever)) actually creates a new list of numbers, and then you work with the numbers that are handed to you from that list. What you really want to do is just work with objects that are handed to you from whatever.

While we're at it, we can pull out the common s['radius'] bit that is checked several times, and put all the if-checks for the bounding box on one line. Oh, and we don't need a separate 'tmpRad', and I assume the 'num's are already ints and don't need to be converted (if they do, why? Why not just have them converted ahead of time?)

None of this will make a huge difference, but it at least makes it easier to read, and definitely doesn't hurt.

filteredList = []
for s in sList:
  radius = s['radius']
  minx = s['x'] - radius
  maxx = s['x'] + radius
  miny = s['y'] - radius
  maxy = s['y'] + radius
  minz = s['z'] - radius
  maxz = s['z'] + radius

  for n in nList:
    if (minx <= n['x'] <= maxx) and (miny <= n['y'] <= maxy) and \
       (minz <= n['z'] <= maxz) and (findRadius(s, n) <= radius):
      filteredList.append(n['num'])

Now it's at least clear what's going on.

However, for the scale of the problem we're working with, it sounds like we're going to need algorithmic improvements. What you probably want to do here is use some kind of BSP (binary space partitioning) technique. The way this works is:

First, we rearrange the nList into a tree. We cut it up into 8 smaller lists, based on whether x > 0, whether y > 0 and whether z > 0 for each point (8 combinations of the 3 boolean results). Then each of those gets cut into 8 again, using the same sort of criteria - e.g. if the possible range for x/y/z is -10..10, then we cut the "x > 0, y > 0, z > 0" list up according to whether x > 5, y > 5, z > 5, etc. You get the idea.

For each point in the sList, we check whether minx > 0, etc. The beautiful part: if minx > 0, we don't have to check any of the 'x < 0' lists, and if maxx < 0, we don't have to check any of the 'x > 0' lists. And so forth. We figure out which of the 8 "octants" of the space the bounding box intersects with; and for each of those, we recursively check the appropriate octants of those octants, etc. until we get to the leaves of the tree, and then we do the normal point-in-bounding-box, then point-in-sphere tests.


来源: stackexchange

问:
Nested JSON object - object notation response is undefined
I hope someone can assist.

I have the following example of a JSON object which I save to my mongoDB via mongoose:

```<code>{"@context":"https://w3id.org/chainpoint/v2",
"type":"ChainpointSHA256v2",
"targetHash":"5eaad1259897efd03dc8ea30d1a0d717fec7ec23b6b1487ad689353a240d92a6",
    "merkleRoot":"6d6fd23027665e754b2af5fe351bd7096e13ad5706402d24c26afe8db88f95c7",
        "proof":[{"right":"6a7a3efc12b60355bedcd82d2045f56589bca7090125a100128c70ff79031fc7"}],
        "anchors":[{"type":"BTCOpReturn",
    "sourceId":"6452eae85d1450b0b1f1104c07d105991a32f0a7c44a449268ceaebf6599566f"}]}
</code>```

I have setup my "Anchor" model in Mongoose to save this as an Object.

In my code, The Object is indeed an Object, when I check the type.

When I do the following in code, the value is successfully printed (where the mongoose model is "Anchor"), and "anchor.receipt" is the exact content as printed in the code snippet above:

```<code>console.log('***Receipt for ID: ' + anchor.receipt);
</code>```

The PROBLEM comes in when I try and do the following. The result for both the below is "undefined":

```<code>console.log('***targetHash for ID: ' + anchor.receipt.targetHash);
console.log('***MerkleRoot for ID: ' + anchor.receipt.merkleRoot);
</code>```

I am also trying to get the following working, but it gives an error, saying the "0" is not defined:

```<code>console.log('***SourceId for ID: ' + anchor.receipt.anchors[0].sourceId);
</code>```

SO, as you can see :), I am having issues retrieving the values in the nested JSON object. ANY help will be GREATLY appreciated.

Thanks!

答:
Yay! Solved:

JSON.parse was the answer. Hopefully this can help someone else in future.

```<code>var data3 = JSON.parse(anchor.receipt);
console.log('***SourceId for ID: ' + data3.anchors[0].sourceId);
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I hope someone can assist.

I have the following example of a JSON object which I save to my mongoDB via mongoose:

{"@context":"https://w3id.org/chainpoint/v2",
"type":"ChainpointSHA256v2",
"targetHash":"5eaad1259897efd03dc8ea30d1a0d717fec7ec23b6b1487ad689353a240d92a6",
    "merkleRoot":"6d6fd23027665e754b2af5fe351bd7096e13ad5706402d24c26afe8db88f95c7",
        "proof":[{"right":"6a7a3efc12b60355bedcd82d2045f56589bca7090125a100128c70ff79031fc7"}],
        "anchors":[{"type":"BTCOpReturn",
    "sourceId":"6452eae85d1450b0b1f1104c07d105991a32f0a7c44a449268ceaebf6599566f"}]}

I have setup my "Anchor" model in Mongoose to save this as an Object.

In my code, The Object is indeed an Object, when I check the type.

When I do the following in code, the value is successfully printed (where the mongoose model is "Anchor"), and "anchor.receipt" is the exact content as printed in the code snippet above:

console.log('***Receipt for ID: ' + anchor.receipt);

The PROBLEM comes in when I try and do the following. The result for both the below is "undefined":

console.log('***targetHash for ID: ' + anchor.receipt.targetHash);
console.log('***MerkleRoot for ID: ' + anchor.receipt.merkleRoot);

I am also trying to get the following working, but it gives an error, saying the "0" is not defined:

console.log('***SourceId for ID: ' + anchor.receipt.anchors[0].sourceId);

SO, as you can see :), I am having issues retrieving the values in the nested JSON object. ANY help will be GREATLY appreciated.

Thanks!

Body:
Yay! Solved:

JSON.parse was the answer. Hopefully this can help someone else in future.

var data3 = JSON.parse(anchor.receipt);
console.log('***SourceId for ID: ' + data3.anchors[0].sourceId);


问:
I am trying to call on a text input with javascript
I am trying to check to make sure a form is complete, here is a piece of my code
checking the password

function checkpass()
{

    var pass1 = document.getElementById('pass1');
    var pass2 = document.getElementById('pass2');

    var message = document.getElementById('confirmMessage');

    var goodColor = "#66cc66";
    var badColor = "#ff6666";

    if(pass1.value == pass2.value){

        pass2.style.backgroundColor = goodColor;
        message.style.color = goodColor;
        message.innerHTML = "Passwords Match!"
    }else{

        pass2.style.backgroundColor = badColor;
        message.style.color = badColor;
        message.innerHTML = "Passwords Do Not Match!"
    }
}  ```
<pre class="snippet-code-html lang-html prettyprint-override"><code><label >Password:</label>
            <input type="password" name="pass1" id="pass1">
      <p></p>

        <label >Verify Password:</label>
        <input type="password" name="pass2" id="pass2" onBlur="checkpass()">
<span id="confirmMessage" class="confirmMessage"></span></code>```

this works, but when I try to do something similar with the name input it does not work

```<code> <input type="text" name="name1" id="name1" onblur="checkname">
 <label>First Name</label>
function checkname(){var name1 = document.getElementById('name1');if (name1 == null) {alert('entername');}}
</code>```

If you have can tell me a simple error I have made that makes me look like a idiot that would be great, or if you could tell me a better way to do the whole thing that would also be great.
Any help you can offer will be much appreciated.

答:
You have written this wrong

```<code>onblur="checkname"
</code>```

it should be as below

```<code>onblur="checkname()"
</code>```

function checkname(){
  var name1 = document.getElementById('name1');

    console.log('name1');
  }```
<pre class="snippet-code-html lang-html prettyprint-override"><code><input type="text" name="name1" id="name1" onblur="checkname()">
 <label>First Name</label> </code>```

Body:
I am trying to check to make sure a form is complete, here is a piece of my code
checking the password

function checkpass()
{

    var pass1 = document.getElementById('pass1');
    var pass2 = document.getElementById('pass2');

    var message = document.getElementById('confirmMessage');

    var goodColor = "#66cc66";
    var badColor = "#ff6666";

    if(pass1.value == pass2.value){

        pass2.style.backgroundColor = goodColor;
        message.style.color = goodColor;
        message.innerHTML = "Passwords Match!"
    }else{

        pass2.style.backgroundColor = badColor;
        message.style.color = badColor;
        message.innerHTML = "Passwords Do Not Match!"
    }
}

Password:
            <input type="password" name="pass1" id="pass1">

        Verify Password:
        <input type="password" name="pass2" id="pass2" onBlur="checkpass()">

this works, but when I try to do something similar with the name input it does not work

 <input type="text" name="name1" id="name1" onblur="checkname">
 First Name
function checkname(){var name1 = document.getElementById('name1');if (name1 == null) {alert('entername');}}

If you have can tell me a simple error I have made that makes me look like a idiot that would be great, or if you could tell me a better way to do the whole thing that would also be great.
Any help you can offer will be much appreciated.

Body:
You have written this wrong

onblur="checkname"

it should be as below

onblur="checkname()"

function checkname(){
  var name1 = document.getElementById('name1');

    console.log('name1');
  }

<input type="text" name="name1" id="name1" onblur="checkname()">
 <label>First Name</label>


问:
Cannot create DocumentFragment storing td, tr or th?
Is it possible to have DocumentFragments contain tr, th or td tags?

If I do this:

```<code>var template = document.createRange().createContextualFragment(
        '<table></table>'
    );

    console.log(template.childNodes);
</code>```

I get the output of [table].

If I do this:

```<code>var template = document.createRange().createContextualFragment(
        '<td></td>'
    );

    console.log(template.childNodes);
</code>```

I get the output of []!!!?!?

If I do this:

```<code>var template = document.createRange().createContextualFragment(
        '<td><p></p></td>'
    );

    console.log(template.childNodes);
</code>```

I get [p]??!?!?!??!?!??!

And finally if I do this:

```<code>var template = document.createRange().createContextualFragment(
        '<span><td></td></span>'
    );

    console.log(template.childNodes);
</code>```

I get [span] - where's the td gone??!

I don't understand the inconsistency here. Is it possible for document fragments to only hold certain elements? What I would like to do is do something akin to the second this above, and then retrieve the td using querySelector.

Thanks

答:
Solution 1

Use createDocumentFragment(), create a  element, and add it to the DocumentFragment with appendChild():

```<code>var frag = document.createDocumentFragment()
frag.appendChild( document.createElement( 'td' ) )
console.log( frag.childNodes )  // output => [td]
</code>```

Solution 2

Create a <template> element, add HTML content to innerHTML, then get the DocumentFragment from the content property:

```<code>var template = document.createElement( 'template' )
template.innerHTML = '<td></td>'
var frag = template.content
console.log( frag.childNodes )   // output => [td]
</code>```

Body:
Is it possible to have DocumentFragments contain tr, th or td tags?

If I do this:

var template = document.createRange().createContextualFragment(
        '

'
    );

    console.log(template.childNodes);

I get the output of [table].

If I do this:

var template = document.createRange().createContextualFragment(
        '	'
    );

    console.log(template.childNodes);

I get the output of []!!!?!?

If I do this:

var template = document.createRange().createContextualFragment(
        '

	'
    );

    console.log(template.childNodes);

I get [p]??!?!?!??!?!??!

And finally if I do this:

var template = document.createRange().createContextualFragment(
        '	'
    );

    console.log(template.childNodes);

I get [span] - where's the td gone??!

I don't understand the inconsistency here. Is it possible for document fragments to only hold certain elements? What I would like to do is do something akin to the second this above, and then retrieve the td using querySelector.

Thanks

Body:
Solution 1

Use createDocumentFragment(), create a <td> element, and add it to the DocumentFragment with appendChild():

var frag = document.createDocumentFragment()
frag.appendChild( document.createElement( 'td' ) )
console.log( frag.childNodes )  // output => [td]

Solution 2

Create a <template> element, add HTML content to innerHTML, then get the DocumentFragment from the content property:

var template = document.createElement( 'template' )
template.innerHTML = '<td></td>'
var frag = template.content
console.log( frag.childNodes )   // output => [td]

ContentLicense: CC BY-SA 4.0


问:
UINavigationController push pop when hide navigation bar
I Have two ViewControlers (ControllerA , ControllerB) ,both of them are hiding navigation bar in viewWillAppear , and showing navigationBar in viewWillDisappear( because sometimes ,the controller push them in has to make the bar be shown)

Now , i have a problem when i got ControllerA in navigation stack , and in ControllerA , i have to push ControllerB .

because the push animation will call A's viewWillDisappear , so in the animation . the bar will be show and hide quickly , same problem happed in pop animation .

how to do this kind of push&pop nicely when viewControllers got different show/hide navigation setting?

答:
OK ,i got a solution seems work well , and i share it here
1st create a catetory of uiviewcontroller

```<code>#import <UIKit/UIKit.h>

#pragma mark Catalog Property Synthesize Support
#import <objc/runtime.h>
#define SYNTHESIZE_CATALOG_OBJ_PROPERTY(propertyGetter, propertySetter)                                                             \
- (id) propertyGetter {                                                                                \
return objc_getAssociatedObject(self, @selector( propertyGetter ));                                                             \
}                                                                                \
- (void) propertySetter (id)obj{                                                                                \
objc_setAssociatedObject(self, @selector( propertyGetter ), obj, OBJC_ASSOCIATION_RETAIN_NONATOMIC);                            \
}

#define SYNTHESIZE_CATALOG_VALUE_PROPERTY(valueType, propertyGetter, propertySetter)                                                \
- (valueType) propertyGetter {                                                                                \
valueType ret = {0};                                                                                \
[objc_getAssociatedObject(self, @selector( propertyGetter )) getValue:&ret];                                                    \
return ret;                                                                                \
}                                                                                \
- (void) propertySetter (valueType)value{                                                                                \
NSValue *valueObj = [NSValue valueWithBytes:&value objCType:@encode(valueType)];                                                \
objc_setAssociatedObject(self, @selector( propertyGetter ), valueObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC);                       \
}

@interface UIViewController (NavigationBar)
@property(nonatomic,assign) BOOL needBarHide;
- (BOOL)checkPreviousControllerHideFlagInViewWillDisappear;
@end
</code>```

and the implementation

```<code>#import "UIViewController+NavigationBar.h"
@implementation UIViewController (NavigationBar)
SYNTHESIZE_CATALOG_VALUE_PROPERTY(BOOL, needBarHide, setNeedBarHide:)

- (BOOL)checkPreviousControllerHideFlagInViewWillDisappear
{
    BOOL lastVCFlag =  [self.navigationController.viewControllers lastObject].needBarHide;
    return lastVCFlag;
}
@end
</code>```

in every class implementation which want to hide bar, do it like this:(the thing must be noticed is that set the needBarHide flag in the init method you use)

```<code>@implementation RedViewController

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self)
    {
        self.needBarHide = YES;
    }
    return self;
}

- (instancetype) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nil];
    if (self)
    {
        self.needBarHide = YES;
    }
    return self;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.navigationController setNavigationBarHidden:YES animated:YES];
    self.delegateObject = self.navigationController.interactivePopGestureRecognizer.delegate;
    self.navigationController.interactivePopGestureRecognizer.delegate = self;
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    BOOL hide = [self checkPreviousControllerHideFlagInViewWillDisappear];
    [self.navigationController setNavigationBarHidden:hide animated:YES];
    NSLog(@"red viewWillDisappear hide:%d",hide);

    self.navigationController.interactivePopGestureRecognizer.delegate = self.delegateObject;
}

@end
</code>```

Body:
OK ,i got a solution seems work well , and i share it here
1st create a catetory of uiviewcontroller

#import <UIKit/UIKit.h>

#pragma mark Catalog Property Synthesize Support
#import <objc/runtime.h>
#define SYNTHESIZE_CATALOG_OBJ_PROPERTY(propertyGetter, propertySetter)                                                             \
- (id) propertyGetter {                                                                                \
return objc_getAssociatedObject(self, @selector( propertyGetter ));                                                             \
}                                                                                \
- (void) propertySetter (id)obj{                                                                                \
objc_setAssociatedObject(self, @selector( propertyGetter ), obj, OBJC_ASSOCIATION_RETAIN_NONATOMIC);                            \
}

#define SYNTHESIZE_CATALOG_VALUE_PROPERTY(valueType, propertyGetter, propertySetter)                                                \
- (valueType) propertyGetter {                                                                                \
valueType ret = {0};                                                                                \
[objc_getAssociatedObject(self, @selector( propertyGetter )) getValue:&ret];                                                    \
return ret;                                                                                \
}                                                                                \
- (void) propertySetter (valueType)value{                                                                                \
NSValue *valueObj = [NSValue valueWithBytes:&value objCType:@encode(valueType)];                                                \
objc_setAssociatedObject(self, @selector( propertyGetter ), valueObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC);                       \
}

@interface UIViewController (NavigationBar)
@property(nonatomic,assign) BOOL needBarHide;
- (BOOL)checkPreviousControllerHideFlagInViewWillDisappear;
@end

and the implementation

#import "UIViewController+NavigationBar.h"
@implementation UIViewController (NavigationBar)
SYNTHESIZE_CATALOG_VALUE_PROPERTY(BOOL, needBarHide, setNeedBarHide:)

- (BOOL)checkPreviousControllerHideFlagInViewWillDisappear
{
    BOOL lastVCFlag =  [self.navigationController.viewControllers lastObject].needBarHide;
    return lastVCFlag;
}
@end

in every class implementation which want to hide bar, do it like this:(the thing must be noticed is that set the needBarHide flag in the init method you use)

@implementation RedViewController

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self)
    {
        self.needBarHide = YES;
    }
    return self;
}

- (instancetype) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nil];
    if (self)
    {
        self.needBarHide = YES;
    }
    return self;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.navigationController setNavigationBarHidden:YES animated:YES];
    self.delegateObject = self.navigationController.interactivePopGestureRecognizer.delegate;
    self.navigationController.interactivePopGestureRecognizer.delegate = self;
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    BOOL hide = [self checkPreviousControllerHideFlagInViewWillDisappear];
    [self.navigationController setNavigationBarHidden:hide animated:YES];
    NSLog(@"red viewWillDisappear hide:%d",hide);

    self.navigationController.interactivePopGestureRecognizer.delegate = self.delegateObject;
}

@end


问:
Which is the best method to perform string concatenation in PHP?
In php we can append strings in many ways.

```<code>            Method 1
            ----------------------------
            $sql  = "SELECT field1, ";
            $sql .= "       field2, ";
            $sql .= "       field3, ";
            $sql .= "       field4, ";
            $sql .= "FROM   table1 ";
            $sql .= "WHERE  condition1 = '".$value."' " ;

            Method 2
            ----------------------------
            $sql  = 'SELECT field1, ';
            $sql .= '       field2, ';
            $sql .= '       field3, ';
            $sql .= '       field4, ';
            $sql .= 'FROM   table1 ';
            $sql .= 'WHERE  condition1 = "'.$value.'" ' ;

            Method 3
            ----------------------------
            $sql  = 'SELECT field1,
                           field2,
                           field3,
                           field4,
                    FROM   table1
                    WHERE  condition1 = "'.$value.'" ' ;

            Method 4
            ----------------------------
            $str = <<<HEREDOC
                    SELECT field1,
                           field2,
                           field3,
                           field4,
                    FROM   table1
                    WHERE  condition1 = "$value"
            HEREDOC;
</code>```

Which of the above is the best approach? Are there any other methods which will result in better performance?

答:
I vote for Method 3.

The less concatenation operations, the better.

Also, you should use single quotes as often as possible to avoid the PHP parser having to interpolate variables inside your strings.

Body:
In php we can append strings in many ways.

            Method 1
            ----------------------------
            $sql  = "SELECT field1, ";
            $sql .= "       field2, ";
            $sql .= "       field3, ";
            $sql .= "       field4, ";
            $sql .= "FROM   table1 ";
            $sql .= "WHERE  condition1 = '".$value."' " ;

            Method 2
            ----------------------------
            $sql  = 'SELECT field1, ';
            $sql .= '       field2, ';
            $sql .= '       field3, ';
            $sql .= '       field4, ';
            $sql .= 'FROM   table1 ';
            $sql .= 'WHERE  condition1 = "'.$value.'" ' ;

            Method 3
            ----------------------------
            $sql  = 'SELECT field1,
                           field2,
                           field3,
                           field4,
                    FROM   table1
                    WHERE  condition1 = "'.$value.'" ' ;

            Method 4
            ----------------------------
            $str = <<<HEREDOC
                    SELECT field1,
                           field2,
                           field3,
                           field4,
                    FROM   table1
                    WHERE  condition1 = "$value"
            HEREDOC;

Which of the above is the best approach? Are there any other methods which will result in better performance?

ContentLicense: CC BY-SA 2.5


问:
PHP S3 upload progress
This has gone around a number of times but I'm still a bit bewildered. A lot of answers only copncern themselves with talking about upload progress bars and not getting the actual upload progress from an S3 upload.

I have read a number of questions and found a number of software pieces but I am still no closer to understanding the fundamental question of S3 uploads.

Is there a way of uploading to S3 while understanding the progress of that upload without having to use my own app servers resources to store the file in the temp directory first?

Do I have to store the file on my own server first and then push to S3? I have heard people talk about streaming bit at a time to S3 (one chunk at a time) but I am unsure what this involves. Imagine I was uploading from client side in a HTML page how would I stream the file chunk by chunk from a multi-part from as it comes in? (I don't see any example of that only an example of when the file is already on your system and you know the chunks which is kinda useless tbh).

There is of course an example of upload progress in the API docs but again that is assuming the file is on your server first and is not coming from another computer supplied by the user.

EDIT: My original thought was to make a PHP script that could ping AWS once every so oftern getting upload progress. I am looking through the API to see if they do support something like that but atm no luck. Let me know if there is something...

Further EDIT: Is flash the only way to go with this?

Thanks,

答:
Yes,you can do this by modifying s3.php like this,

```<?php
class S3Withprogressbar {
// ACL flags
const ACL_PRIVATE = 'private';
const ACL_PUBLIC_READ = 'public-read';
const ACL_PUBLIC_READ_WRITE = 'public-read-write';
private static $__accessKey; // AWS Access key
private static $__secretKey; // AWS Secret key
public static $_uploadProgressFileName="" ;//uploadProgressFileName
public function __construct($accessKey = null, $secretKey = null) {
if ($accessKey !== null && $secretKey !== null)
self::setAuth($accessKey, $secretKey);
}
public static function setAuth($accessKey, $secretKey) {
self::$__accessKey = $accessKey;
self::$__secretKey = $secretKey;
}
public static function listBuckets($detailed = false) {
$rest = new S3Request('GET', '', '');
$rest = $rest->getResponse();
if ($rest->error === false && $rest->code !== 200)
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
trigger_error(sprintf("S3Withprogressbar::listBuckets(): [%s] %s", $rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
$results = array(); //var_dump($rest->body);
if (!isset($rest->body->Buckets)) return $results;
if ($detailed) {
if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName))
$results['owner'] = array(
'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->ID
);
$results['buckets'] = array();
foreach ($rest->body->Buckets->Bucket as $b)
$results['buckets'][] = array(
'name' => (string)$b->Name, 'time' => strtotime((string)$b->CreationDate)
);
} else
foreach ($rest->body->Buckets->Bucket as $b) $results[] = (string)$b->Name;
return $results;
}
public static function getBucket($bucket, $prefix = null, $marker = null, $maxKeys = null) {
$rest = new S3Request('GET', $bucket, '');
if ($prefix !== null && $prefix !== '') $rest->setParameter('prefix', $prefix);
if ($marker !== null && $prefix !== '') $rest->setParameter('marker', $marker);
if ($maxKeys !== null && $prefix !== '') $rest->setParameter('max-keys', $maxKeys);
$response = $rest->getResponse();
if ($response->error === false && $response->code !== 200)
$response->error = array('code' => $response->code, 'message' => 'Unexpected HTTP status');
if ($response->error !== false) {
trigger_error(sprintf("S3Withprogressbar::getBucket(): [%s] %s", $response->error['code'], $response->error['message']), E_USER_WARNING);
return false;
}
$results = array();
$lastMarker = null;
if (isset($response->body, $response->body->Contents))
foreach ($response->body->Contents as $c) {
$results[(string)$c->Key] = array(
'name' => (string)$c->Key,
'time' => strToTime((string)$c->LastModified),
'size' => (int)$c->Size,
'hash' => substr((string)$c->ETag, 1, -1)
);
$lastMarker = (string)$c->Key;
//$response->body->IsTruncated = 'true'; break;
}
if (isset($response->body->IsTruncated) &&
(string)$response->body->IsTruncated == 'false') return $results;
// Loop through truncated results if maxKeys isn't specified
if ($maxKeys == null && $lastMarker !== null && (string)$response->body->IsTruncated == 'true')
do {
$rest = new S3Request('GET', $bucket, '');
if ($prefix !== null) $rest->setParameter('prefix', $prefix);
$rest->setParameter('marker', $lastMarker);
if (($response = $rest->getResponse(true)) == false || $response->code !== 200) break;
if (isset($response->body, $response->body->Contents))
foreach ($response->body->Contents as $c) {
$results[(string)$c->Key] = array(
'name' => (string)$c->Key,
'time' => strToTime((string)$c->LastModified),
'size' => (int)$c->Size,
'hash' => substr((string)$c->ETag, 1, -1)
);
$lastMarker = (string)$c->Key;
}
} while ($response !== false && (string)$response->body->IsTruncated == 'true');
return $results;
}
public function putBucket($bucket, $acl = self::ACL_PRIVATE) {
$rest = new S3Request('PUT', $bucket, '');
$rest->setAmzHeader('x-amz-acl', $acl);
$rest = $rest->getResponse();
if ($rest->error === false && $rest->code !== 200)
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
//trigger_error(sprintf("S3Withprogressbar::putBucket({$bucket}): [%s] %s", $rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
return true;
}
public function deleteBucket($bucket = '') {
$rest = new S3Request('DELETE', $bucket);
$rest = $rest->getResponse();
if ($rest->error === false && $rest->code !== 204)
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
trigger_error(sprintf("S3Withprogressbar::deleteBucket({$bucket}): [%s] %s",
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
return true;
}
public static function inputFile($file, $md5sum = true) {
if (!file_exists($file) || !is_file($file) || !is_readable($file)) {
trigger_error('S3Withprogressbar::inputFile(): Unable to open input file: '.$file, E_USER_WARNING);
return false;
}
return array('file' => $file, 'size' => filesize($file),
'md5sum' => $md5sum !== false ? (is_string($md5sum) ? $md5sum :
base64_encode(md5_file($file, true))) : '');
}
public static function inputResource(&$resource, $bufferSize, $md5sum = '') {
if (!is_resource($resource) || $bufferSize <= 0) {
trigger_error('S3Withprogressbar::inputResource(): Invalid resource or buffer size', E_USER_WARNING);
return false;
}
$input = array('size' => $bufferSize, 'md5sum' => $md5sum);
$input['fp'] =& $resource;
return $input;
}
// Modified Function with one more  parameter $uploadProgressFileName
public static function putObject($input, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = null,$uploadProgressFileName) {
if ($input == false) return false;
$rest = new S3Request('PUT', $bucket, $uri);
// Set public variable value($uploadProgressFileName) in S3Request class
$rest->uploadProgressFileName = $uploadProgressFileName;
if (is_string($input)) $input = array(
'data' => $input, 'size' => strlen($input),
'md5sum' => base64_encode(md5($input, true))
);
// Data
if (isset($input['fp']))
$rest->fp =& $input['fp'];
elseif (isset($input['file']))
$rest->fp = @fopen($input['file'], 'rb');
elseif (isset($input['data']))
$rest->data = $input['data'];
// Content-Length (required)
if (isset($input['size']) && $input['size'] > 0)
$rest->size = $input['size'];
else {
if (isset($input['file']))
$rest->size = filesize($input['file']);
elseif (isset($input['data']))
$rest->size = strlen($input['data']);
}
// Content-Type
if ($contentType !== null)
$input['type'] = $contentType;
elseif (!isset($input['type']) && isset($input['file']))
$input['type'] = self::__getMimeType($input['file']);
else
$input['type'] = 'application/octet-stream';
// We need to post with the content-length and content-type, MD5 is optional
if ($rest->size > 0 && ($rest->fp !== false || $rest->data !== false)) {
$rest->setHeader('Content-Type', $input['type']);
if (isset($input['md5sum'])) $rest->setHeader('Content-MD5', $input['md5sum']);
$rest->setAmzHeader('x-amz-acl', $acl);
foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
$rest->getResponse();
} else
$rest->response->error = array('code' => 0, 'message' => 'Missing input parameters');
if ($rest->response->error === false && $rest->response->code !== 200)
$rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
if ($rest->response->error !== false) {
//trigger_error(sprintf("S3Withprogressbar::putObject(): [%s] %s", $rest->response->error['code'], $rest->response->error['message']), E_USER_WARNING);
return false;
}
return true;
}
// Modified Function with one more  parameter $uploadProgressFileName
public static function putObjectFile($file, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = null,$uploadProgressFileName) {
return self::putObject(S3Withprogressbar::inputFile($file), $bucket, $uri, $acl, $metaHeaders, $contentType,$uploadProgressFileName);
}
public function putObjectString($string, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = 'text/plain') {
return self::putObject($string, $bucket, $uri, $acl, $metaHeaders, $contentType);
}
public static function getObject($bucket = '', $uri = '', $saveTo = false) {
$rest = new S3Request('GET', $bucket, $uri);
if ($saveTo !== false) {
if (is_resource($saveTo))
$rest->fp =& $saveTo;
else
if (($rest->fp = @fopen($saveTo, 'wb')) == false)
$rest->response->error = array('code' => 0, 'message' => 'Unable to open save file for writing: '.$saveTo);
}
if ($rest->response->error === false) $rest->getResponse();
if ($rest->response->error === false && $rest->response->code !== 200)
$rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
if ($rest->response->error !== false) {
trigger_error(sprintf("S3Withprogressbar::getObject({$bucket}, {$uri}): [%s] %s",
$rest->response->error['code'], $rest->response->error['message']), E_USER_WARNING);
return false;
}
$rest->file = realpath($saveTo);
return $rest->response;
}
public static function getObjectInfo($bucket = '', $uri = '', $returnInfo = true) {
$rest = new S3Request('HEAD', $bucket, $uri);
$rest = $rest->getResponse();
if ($rest->error === false && ($rest->code !== 200 && $rest->code !== 404))
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
trigger_error(sprintf("S3Withprogressbar::getObjectInfo({$bucket}, {$uri}): [%s] %s",
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
return $rest->code == 200 ? $returnInfo ? $rest->headers : true : false;
}
public static function setBucketLogging($bucket, $targetBucket, $targetPrefix) {
$dom = new DOMDocument;
$bucketLoggingStatus = $dom->createElement('BucketLoggingStatus');
$bucketLoggingStatus->setAttribute('xmlns', 'http://s3.amazonaws.com/doc/2006-03-01/');
$loggingEnabled = $dom->createElement('LoggingEnabled');
$loggingEnabled->appendChild($dom->createElement('TargetBucket', $targetBucket));
$loggingEnabled->appendChild($dom->createElement('TargetPrefix', $targetPrefix));
// TODO: Add TargetGrants
$bucketLoggingStatus->appendChild($loggingEnabled);
$dom->appendChild($bucketLoggingStatus);
$rest = new S3Request('PUT', $bucket, '');
$rest->setParameter('logging', null);
$rest->data = $dom->saveXML();
$rest->size = strlen($rest->data);
$rest->setHeader('Content-Type', 'application/xml');
$rest = $rest->getResponse();
if ($rest->error === false && $rest->code !== 200)
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
trigger_error(sprintf("S3Withprogressbar::setBucketLogging({$bucket}, {$uri}): [%s] %s",
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
return true;
}
public static function getBucketLogging($bucket = '') {
$rest = new S3Request('GET', $bucket, '');
$rest->setParameter('logging', null);
$rest = $rest->getResponse();
if ($rest->error === false && $rest->code !== 200)
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
trigger_error(sprintf("S3Withprogressbar::getBucketLogging({$bucket}): [%s] %s",
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
if (!isset($rest->body->LoggingEnabled)) return false; // No logging
return array(
'targetBucket' => (string)$rest->body->LoggingEnabled->TargetBucket,
'targetPrefix' => (string)$rest->body->LoggingEnabled->TargetPrefix,
);
}
public static function setAccessControlPolicy($bucket, $uri = '', $acp = array()) {
$dom = new DOMDocument;
$dom->formatOutput = true;
$accessControlPolicy = $dom->createElement('AccessControlPolicy');
$accessControlList = $dom->createElement('AccessControlList');
// It seems the owner has to be passed along too
$owner = $dom->createElement('Owner');
$owner->appendChild($dom->createElement('ID', $acp['owner']['id']));
$owner->appendChild($dom->createElement('DisplayName', $acp['owner']['name']));
$accessControlPolicy->appendChild($owner);
foreach ($acp['acl'] as $g) {
$grant = $dom->createElement('Grant');
$grantee = $dom->createElement('Grantee');
$grantee->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
if (isset($g['id'])) { // CanonicalUser (DisplayName is omitted)
$grantee->setAttribute('xsi:type', 'CanonicalUser');
$grantee->appendChild($dom->createElement('ID', $g['id']));
} elseif (isset($g['email'])) { // AmazonCustomerByEmail
$grantee->setAttribute('xsi:type', 'AmazonCustomerByEmail');
$grantee->appendChild($dom->createElement('EmailAddress', $g['email']));
} elseif ($g['type'] == 'Group') { // Group
$grantee->setAttribute('xsi:type', 'Group');
$grantee->appendChild($dom->createElement('URI', $g['uri']));
}
$grant->appendChild($grantee);
$grant->appendChild($dom->createElement('Permission', $g['permission']));
$accessControlList->appendChild($grant);
}
$accessControlPolicy->appendChild($accessControlList);
$dom->appendChild($accessControlPolicy);
$rest = new S3Request('PUT', $bucket, '');
$rest->setParameter('acl', null);
$rest->data = $dom->saveXML();
$rest->size = strlen($rest->data);
$rest->setHeader('Content-Type', 'application/xml');
$rest = $rest->getResponse();
if ($rest->error === false && $rest->code !== 200)
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
trigger_error(sprintf("S3Withprogressbar::setAccessControlPolicy({$bucket}, {$uri}): [%s] %s",
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
return true;
}
public static function getAccessControlPolicy($bucket, $uri = '') {
$rest = new S3Request('GET', $bucket, $uri);
$rest->setParameter('acl', null);
$rest = $rest->getResponse();
if ($rest->error === false && $rest->code !== 200)
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
trigger_error(sprintf("S3Withprogressbar::getAccessControlPolicy({$bucket}, {$uri}): [%s] %s",
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
$acp = array();
if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName)) {
$acp['owner'] = array(
'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->DisplayName
);
}
if (isset($rest->body->AccessControlList)) {
$acp['acl'] = array();
foreach ($rest->body->AccessControlList->Grant as $grant) {
foreach ($grant->Grantee as $grantee) {
if (isset($grantee->ID, $grantee->DisplayName)) // CanonicalUser
$acp['acl'][] = array(
'type' => 'CanonicalUser',
'id' => (string)$grantee->ID,
'name' => (string)$grantee->DisplayName,
'permission' => (string)$grant->Permission
);
elseif (isset($grantee->EmailAddress)) // AmazonCustomerByEmail
$acp['acl'][] = array(
'type' => 'AmazonCustomerByEmail',
'email' => (string)$grantee->EmailAddress,
'permission' => (string)$grant->Permission
);
elseif (isset($grantee->URI)) // Group
$acp['acl'][] = array(
'type' => 'Group',
'uri' => (string)$grantee->URI,
'permission' => (string)$grant->Permission
);
else continue;
}
}
}
return $acp;
}
public static function deleteObject($bucket = '', $uri = '') {
$rest = new S3Request('DELETE', $bucket, $uri);
$rest = $rest->getResponse();
if ($rest->error === false && $rest->code !== 204)
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
trigger_error(sprintf("S3Withprogressbar::deleteObject(): [%s] %s", $rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
return true;
}
public static function __getMimeType(&$file) {
$type = false;
// Fileinfo documentation says fileinfo_open() will use the
// MAGIC env var for the magic file
if (extension_loaded('fileinfo') && isset($_ENV['MAGIC']) &&
($finfo = finfo_open(FILEINFO_MIME, $_ENV['MAGIC'])) !== false) {
if (($type = finfo_file($finfo, $file)) !== false) {
// Remove the charset and grab the last content-type
$type = explode(' ', str_replace('; charset=', ';charset=', $type));
$type = array_pop($type);
$type = explode(';', $type);
$type = array_shift($type);
}
finfo_close($finfo);
// If anyone is still using mime_content_type()
} elseif (function_exists('mime_content_type'))
$type = mime_content_type($file);
if ($type !== false && strlen($type) > 0) return $type;
// Otherwise do it the old fashioned way
static $exts = array(
'jpg' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png',
'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'ico' => 'image/x-icon',
'swf' => 'application/x-shockwave-flash', 'pdf' => 'application/pdf',
'zip' => 'application/zip', 'gz' => 'application/x-gzip',
'tar' => 'application/x-tar', 'bz' => 'application/x-bzip',
'bz2' => 'application/x-bzip2', 'txt' => 'text/plain',
'asc' => 'text/plain', 'htm' => 'text/html', 'html' => 'text/html',
'xml' => 'text/xml', 'xsl' => 'application/xsl+xml',
'ogg' => 'application/ogg', 'mp3' => 'audio/mpeg', 'wav' => 'audio/x-wav',
'avi' => 'video/x-msvideo', 'mpg' => 'video/mpeg', 'mpeg' => 'video/mpeg',
'mov' => 'video/quicktime', 'flv' => 'video/x-flv', 'php' => 'text/x-php'
);
$ext = strToLower(pathInfo($file, PATHINFO_EXTENSION));
return isset($exts[$ext]) ? $exts[$ext] : 'application/octet-stream';
}
public static function __getSignature($string) {
return 'AWS '.self::$__accessKey.':'.base64_encode(extension_loaded('hash') ?
hash_hmac('sha1', $string, self::$__secretKey, true) : pack('H*', sha1(
(str_pad(self::$__secretKey, 64, chr(0x00)) ^ (str_repeat(chr(0x5c), 64))) .
pack('H*', sha1((str_pad(self::$__secretKey, 64, chr(0x00)) ^
(str_repeat(chr(0x36), 64))) . $string)))));
}
}
final class S3Request {
private $verb, $bucket, $uri, $resource = '', $parameters = array(),
$amzHeaders = array(), $headers = array(
'Host' => '', 'Date' => '', 'Content-MD5' => '', 'Content-Type' => ''
);
public $fp = false, $size = 0, $data = false, $response;
public $uploadProgressFileName;
function __construct($verb, $bucket = '', $uri = '') {
$this->verb = $verb;
$this->bucket = strtolower($bucket);
$this->uri = $uri !== '' ? '/'.$uri : '/';
if ($this->bucket !== '') {
$this->bucket = explode('/', $this->bucket);
$this->resource = '/'.$this->bucket[0].$this->uri;
$this->headers['Host'] = $this->bucket[0].'.s3.amazonaws.com';
$this->bucket = implode('/', $this->bucket);
} else {
$this->headers['Host'] = 's3.amazonaws.com';
if (strlen($this->uri) > 1)
$this->resource = '/'.$this->bucket.$this->uri;
else $this->resource = $this->uri;
}
$this->headers['Date'] = gmdate('D, d M Y H:i:s T');
$this->response = new STDClass;
$this->response->error = false;
$this->response->body  = false;
$CI =& get_instance();
$CI->load->helper('file');
}
public function setParameter($key, $value) {
$this->parameters[$key] = $value;
}
public function setHeader($key, $value) {
$this->headers[$key] = $value;
}
public function setAmzHeader($key, $value) {
$this->amzHeaders[$key] = $value;
}
//:callback function for upload progress.
public function progressCallback_new_curl($new,$download_size, $downloaded_size, $upload_size, $uploaded_size )
{
ob_start();
static $previousProgress = 0;
if ( $upload_size == 0 )
$progress = 0;
else
$progress = round( $uploaded_size * 100 / $upload_size );
if ( $progress > $previousProgress)
{
flush();
$previousProgress = $progress;
$new_file_path = FCPATH.'upload/'.$this->uploadProgressFileName.'.txt'; // modify this line to point to the actual location of the file
write_file($new_file_path, $progress."\n");
// Check for Cancel upload text file and if exists return 1 to interrupt curl upload process.
$cancel_path=FCPATH.'upload/cancel_'.$this->uploadProgressFileName.'.txt';
if(file_exists($cancel_path)){
unlink($cancel_path);
if(file_exists($new_file_path)){
unlink($new_file_path);
}
return 1;
}
}
ob_flush();
flush();
}
public function progressCallback_old_curl($download_size, $downloaded_size, $upload_size, $uploaded_size )
{
ob_start();
static $previousProgress = 0;
if ( $upload_size == 0 )
$progress = 0;
else
$progress = round( $uploaded_size * 100 / $upload_size );
if ( $progress > $previousProgress)
{
flush();
$previousProgress = $progress;
$new_file_path = FCPATH.'upload/'.$this->uploadProgressFileName.'.txt'; // modify this line to point to the actual location of the file
write_file($new_file_path, $progress."\n");
// Check for Cancel upload text file and if exists return 1 to interrupt curl upload process.
$cancel_path=FCPATH.'upload/cancel_'.$this->uploadProgressFileName.'.txt';
if(file_exists($cancel_path)){
unlink($cancel_path);
if(file_exists($new_file_path)){
unlink($new_file_path);
}
return 1;
}
}
ob_flush();
flush();
}
public function getResponse() {
$query = '';
if (sizeof($this->parameters) > 0) {
$query = substr($this->uri, -1) !== '?' ? '?' : '&';
foreach ($this->parameters as $var => $value)
if ($value == null || $value == '') $query .= $var.'&';
else $query .= $var.'='.$value.'&';
$query = substr($query, 0, -1);
$this->uri .= $query;
if (isset($this->parameters['acl']) || !isset($this->parameters['logging']))
$this->resource .= $query;
}
$url = (extension_loaded('openssl')?'https://':'http://').$this->headers['Host'].$this->uri;
//var_dump($this->bucket, $this->uri, $this->resource, $url);
// Basic setup
$curl = curl_init();
curl_setopt($curl, CURLOPT_USERAGENT, 'S3/php');
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curl, CURLOPT_URL, $url);
//:callback function call for upload progress.
curl_setopt($curl, CURLOPT_NOPROGRESS, false);
if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 50500) {
curl_setopt($curl, CURLOPT_PROGRESSFUNCTION,  array($this, 'progressCallback_old_curl'));
} else {
curl_setopt($curl, CURLOPT_PROGRESSFUNCTION,  array($this, 'progressCallback_new_curl'));
}
// Headers
$headers = array(); $amz = array();
foreach ($this->amzHeaders as $header => $value)
if (strlen($value) > 0) $headers[] = $header.': '.$value;
foreach ($this->headers as $header => $value)
if (strlen($value) > 0) $headers[] = $header.': '.$value;
foreach ($this->amzHeaders as $header => $value)
if (strlen($value) > 0) $amz[] = strToLower($header).':'.$value;
$amz = (sizeof($amz) > 0) ? "\n".implode("\n", $amz) : '';
// Authorization string
$headers[] = 'Authorization: ' . S3Withprogressbar::__getSignature(
$this->verb."\n".
$this->headers['Content-MD5']."\n".
$this->headers['Content-Type']."\n".
$this->headers['Date'].$amz."\n".$this->resource
);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);
curl_setopt($curl, CURLOPT_WRITEFUNCTION, array(&$this, '__responseWriteCallback'));
curl_setopt($curl, CURLOPT_HEADERFUNCTION, array(&$this, '__responseHeaderCallback'));
// Request types
switch ($this->verb) {
case 'GET': break;
case 'PUT':
if ($this->fp !== false) {
curl_setopt($curl, CURLOPT_PUT, true);
curl_setopt($curl, CURLOPT_INFILE, $this->fp);
if ($this->size > 0)
curl_setopt($curl, CURLOPT_INFILESIZE, $this->size);
} elseif ($this->data !== false) {
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($curl, CURLOPT_POSTFIELDS, $this->data);
if ($this->size > 0)
curl_setopt($curl, CURLOPT_BUFFERSIZE, $this->size);
} else
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
break;
case 'HEAD':
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'HEAD');
curl_setopt($curl, CURLOPT_NOBODY, true);
break;
case 'DELETE':
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
break;
default: break;
}
// Execute, grab errors
if (curl_exec($curl))
$this->response->code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
else
$this->response->error = array(
'code' => curl_errno($curl),
'message' => curl_error($curl),
'resource' => $this->resource
);
@curl_close($curl);
// Parse body into XML
if ($this->response->error === false && isset($this->response->headers['type']) &&
$this->response->headers['type'] == 'application/xml' && isset($this->response->body)) {
$this->response->body = simplexml_load_string($this->response->body);
// Grab S3 errors
if (!in_array($this->response->code, array(200, 204)) &&
isset($this->response->body->Code, $this->response->body->Message)) {
$this->response->error = array(
'code' => (string)$this->response->body->Code,
'message' => (string)$this->response->body->Message
);
if (isset($this->response->body->Resource))
$this->response->error['resource'] = (string)$this->response->body->Resource;
unset($this->response->body);
}
}
// Clean up file resources
if ($this->fp !== false && is_resource($this->fp)) fclose($this->fp);
return $this->response;
}
private function __responseWriteCallback(&$curl, &$data) {
if ($this->response->code == 200 && $this->fp !== false)
return fwrite($this->fp, $data);
else
$this->response->body .= $data;
return strlen($data);
}
private function __responseHeaderCallback(&$curl, &$data) {
if (($strlen = strlen($data)) <= 2) return $strlen;
if (substr($data, 0, 4) == 'HTTP')
$this->response->code = (int)substr($data, 9, 3);
else {
list($header, $value) = explode(': ', trim($data));
if ($header == 'Last-Modified')
$this->response->headers['time'] = strtotime($value);
elseif ($header == 'Content-Length')
$this->response->headers['size'] = (int)$value;
elseif ($header == 'Content-Type')
$this->response->headers['type'] = $value;
elseif ($header == 'ETag')
$this->response->headers['hash'] = substr($value, 1, -1);
elseif (preg_match('/^x-amz-meta-.*$/', $header))
$this->response->headers[$header] = is_numeric($value) ? (int)$value : $value;
}
return $strlen;
}
}
?>
```

Title: PHP S3 upload progress

Body:
Yes,you can do this by modifying s3.php like this,

<?php
class S3Withprogressbar {
// ACL flags
const ACL_PRIVATE = 'private';
const ACL_PUBLIC_READ = 'public-read';
const ACL_PUBLIC_READ_WRITE = 'public-read-write';
private static $__accessKey; // AWS Access key
private static $__secretKey; // AWS Secret key
public static $_uploadProgressFileName="" ;//uploadProgressFileName
public function __construct($accessKey = null, $secretKey = null) {
if ($accessKey !== null && $secretKey !== null)
self::setAuth($accessKey, $secretKey);
}
public static function setAuth($accessKey, $secretKey) {
self::$__accessKey = $accessKey;
self::$__secretKey = $secretKey;
}
public static function listBuckets($detailed = false) {
$rest = new S3Request('GET', '', '');
$rest = $rest->getResponse();
if ($rest->error === false && $rest->code !== 200)
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
trigger_error(sprintf("S3Withprogressbar::listBuckets(): [%s] %s", $rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
$results = array(); //var_dump($rest->body);
if (!isset($rest->body->Buckets)) return $results;
if ($detailed) {
if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName))
$results['owner'] = array(
'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->ID
);
$results['buckets'] = array();
foreach ($rest->body->Buckets->Bucket as $b)
$results['buckets'][] = array(
'name' => (string)$b->Name, 'time' => strtotime((string)$b->CreationDate)
);
} else
foreach ($rest->body->Buckets->Bucket as $b) $results[] = (string)$b->Name;
return $results;
}
public static function getBucket($bucket, $prefix = null, $marker = null, $maxKeys = null) {
$rest = new S3Request('GET', $bucket, '');
if ($prefix !== null && $prefix !== '') $rest->setParameter('prefix', $prefix);
if ($marker !== null && $prefix !== '') $rest->setParameter('marker', $marker);
if ($maxKeys !== null && $prefix !== '') $rest->setParameter('max-keys', $maxKeys);
$response = $rest->getResponse();
if ($response->error === false && $response->code !== 200)
$response->error = array('code' => $response->code, 'message' => 'Unexpected HTTP status');
if ($response->error !== false) {
trigger_error(sprintf("S3Withprogressbar::getBucket(): [%s] %s", $response->error['code'], $response->error['message']), E_USER_WARNING);
return false;
}
$results = array();
$lastMarker = null;
if (isset($response->body, $response->body->Contents))
foreach ($response->body->Contents as $c) {
$results[(string)$c->Key] = array(
'name' => (string)$c->Key,
'time' => strToTime((string)$c->LastModified),
'size' => (int)$c->Size,
'hash' => substr((string)$c->ETag, 1, -1)
);
$lastMarker = (string)$c->Key;
//$response->body->IsTruncated = 'true'; break;
}
if (isset($response->body->IsTruncated) &&
(string)$response->body->IsTruncated == 'false') return $results;
// Loop through truncated results if maxKeys isn't specified
if ($maxKeys == null && $lastMarker !== null && (string)$response->body->IsTruncated == 'true')
do {
$rest = new S3Request('GET', $bucket, '');
if ($prefix !== null) $rest->setParameter('prefix', $prefix);
$rest->setParameter('marker', $lastMarker);
if (($response = $rest->getResponse(true)) == false || $response->code !== 200) break;
if (isset($response->body, $response->body->Contents))
foreach ($response->body->Contents as $c) {
$results[(string)$c->Key] = array(
'name' => (string)$c->Key,
'time' => strToTime((string)$c->LastModified),
'size' => (int)$c->Size,
'hash' => substr((string)$c->ETag, 1, -1)
);
$lastMarker = (string)$c->Key;
}
} while ($response !== false && (string)$response->body->IsTruncated == 'true');
return $results;
}
public function putBucket($bucket, $acl = self::ACL_PRIVATE) {
$rest = new S3Request('PUT', $bucket, '');
$rest->setAmzHeader('x-amz-acl', $acl);
$rest = $rest->getResponse();
if ($rest->error === false && $rest->code !== 200)
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
//trigger_error(sprintf("S3Withprogressbar::putBucket({$bucket}): [%s] %s", $rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
return true;
}
public function deleteBucket($bucket = '') {
$rest = new S3Request('DELETE', $bucket);
$rest = $rest->getResponse();
if ($rest->error === false && $rest->code !== 204)
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
trigger_error(sprintf("S3Withprogressbar::deleteBucket({$bucket}): [%s] %s",
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
return true;
}
public static function inputFile($file, $md5sum = true) {
if (!file_exists($file) || !is_file($file) || !is_readable($file)) {
trigger_error('S3Withprogressbar::inputFile(): Unable to open input file: '.$file, E_USER_WARNING);
return false;
}
return array('file' => $file, 'size' => filesize($file),
'md5sum' => $md5sum !== false ? (is_string($md5sum) ? $md5sum :
base64_encode(md5_file($file, true))) : '');
}
public static function inputResource(&$resource, $bufferSize, $md5sum = '') {
if (!is_resource($resource) || $bufferSize <= 0) {
trigger_error('S3Withprogressbar::inputResource(): Invalid resource or buffer size', E_USER_WARNING);
return false;
}
$input = array('size' => $bufferSize, 'md5sum' => $md5sum);
$input['fp'] =& $resource;
return $input;
}
// Modified Function with one more  parameter $uploadProgressFileName
public static function putObject($input, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = null,$uploadProgressFileName) {
if ($input == false) return false;
$rest = new S3Request('PUT', $bucket, $uri);
// Set public variable value($uploadProgressFileName) in S3Request class
$rest->uploadProgressFileName = $uploadProgressFileName;
if (is_string($input)) $input = array(
'data' => $input, 'size' => strlen($input),
'md5sum' => base64_encode(md5($input, true))
);
// Data
if (isset($input['fp']))
$rest->fp =& $input['fp'];
elseif (isset($input['file']))
$rest->fp = @fopen($input['file'], 'rb');
elseif (isset($input['data']))
$rest->data = $input['data'];
// Content-Length (required)
if (isset($input['size']) && $input['size'] > 0)
$rest->size = $input['size'];
else {
if (isset($input['file']))
$rest->size = filesize($input['file']);
elseif (isset($input['data']))
$rest->size = strlen($input['data']);
}
// Content-Type
if ($contentType !== null)
$input['type'] = $contentType;
elseif (!isset($input['type']) && isset($input['file']))
$input['type'] = self::__getMimeType($input['file']);
else
$input['type'] = 'application/octet-stream';
// We need to post with the content-length and content-type, MD5 is optional
if ($rest->size > 0 && ($rest->fp !== false || $rest->data !== false)) {
$rest->setHeader('Content-Type', $input['type']);
if (isset($input['md5sum'])) $rest->setHeader('Content-MD5', $input['md5sum']);
$rest->setAmzHeader('x-amz-acl', $acl);
foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
$rest->getResponse();
} else
$rest->response->error = array('code' => 0, 'message' => 'Missing input parameters');
if ($rest->response->error === false && $rest->response->code !== 200)
$rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
if ($rest->response->error !== false) {
//trigger_error(sprintf("S3Withprogressbar::putObject(): [%s] %s", $rest->response->error['code'], $rest->response->error['message']), E_USER_WARNING);
return false;
}
return true;
}
// Modified Function with one more  parameter $uploadProgressFileName
public static function putObjectFile($file, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = null,$uploadProgressFileName) {
return self::putObject(S3Withprogressbar::inputFile($file), $bucket, $uri, $acl, $metaHeaders, $contentType,$uploadProgressFileName);
}
public function putObjectString($string, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = 'text/plain') {
return self::putObject($string, $bucket, $uri, $acl, $metaHeaders, $contentType);
}
public static function getObject($bucket = '', $uri = '', $saveTo = false) {
$rest = new S3Request('GET', $bucket, $uri);
if ($saveTo !== false) {
if (is_resource($saveTo))
$rest->fp =& $saveTo;
else
if (($rest->fp = @fopen($saveTo, 'wb')) == false)
$rest->response->error = array('code' => 0, 'message' => 'Unable to open save file for writing: '.$saveTo);
}
if ($rest->response->error === false) $rest->getResponse();
if ($rest->response->error === false && $rest->response->code !== 200)
$rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
if ($rest->response->error !== false) {
trigger_error(sprintf("S3Withprogressbar::getObject({$bucket}, {$uri}): [%s] %s",
$rest->response->error['code'], $rest->response->error['message']), E_USER_WARNING);
return false;
}
$rest->file = realpath($saveTo);
return $rest->response;
}
public static function getObjectInfo($bucket = '', $uri = '', $returnInfo = true) {
$rest = new S3Request('HEAD', $bucket, $uri);
$rest = $rest->getResponse();
if ($rest->error === false && ($rest->code !== 200 && $rest->code !== 404))
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
trigger_error(sprintf("S3Withprogressbar::getObjectInfo({$bucket}, {$uri}): [%s] %s",
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
return $rest->code == 200 ? $returnInfo ? $rest->headers : true : false;
}
public static function setBucketLogging($bucket, $targetBucket, $targetPrefix) {
$dom = new DOMDocument;
$bucketLoggingStatus = $dom->createElement('BucketLoggingStatus');
$bucketLoggingStatus->setAttribute('xmlns', 'http://s3.amazonaws.com/doc/2006-03-01/');
$loggingEnabled = $dom->createElement('LoggingEnabled');
$loggingEnabled->appendChild($dom->createElement('TargetBucket', $targetBucket));
$loggingEnabled->appendChild($dom->createElement('TargetPrefix', $targetPrefix));
// TODO: Add TargetGrants
$bucketLoggingStatus->appendChild($loggingEnabled);
$dom->appendChild($bucketLoggingStatus);
$rest = new S3Request('PUT', $bucket, '');
$rest->setParameter('logging', null);
$rest->data = $dom->saveXML();
$rest->size = strlen($rest->data);
$rest->setHeader('Content-Type', 'application/xml');
$rest = $rest->getResponse();
if ($rest->error === false && $rest->code !== 200)
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
trigger_error(sprintf("S3Withprogressbar::setBucketLogging({$bucket}, {$uri}): [%s] %s",
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
return true;
}
public static function getBucketLogging($bucket = '') {
$rest = new S3Request('GET', $bucket, '');
$rest->setParameter('logging', null);
$rest = $rest->getResponse();
if ($rest->error === false && $rest->code !== 200)
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
trigger_error(sprintf("S3Withprogressbar::getBucketLogging({$bucket}): [%s] %s",
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
if (!isset($rest->body->LoggingEnabled)) return false; // No logging
return array(
'targetBucket' => (string)$rest->body->LoggingEnabled->TargetBucket,
'targetPrefix' => (string)$rest->body->LoggingEnabled->TargetPrefix,
);
}
public static function setAccessControlPolicy($bucket, $uri = '', $acp = array()) {
$dom = new DOMDocument;
$dom->formatOutput = true;
$accessControlPolicy = $dom->createElement('AccessControlPolicy');
$accessControlList = $dom->createElement('AccessControlList');
// It seems the owner has to be passed along too
$owner = $dom->createElement('Owner');
$owner->appendChild($dom->createElement('ID', $acp['owner']['id']));
$owner->appendChild($dom->createElement('DisplayName', $acp['owner']['name']));
$accessControlPolicy->appendChild($owner);
foreach ($acp['acl'] as $g) {
$grant = $dom->createElement('Grant');
$grantee = $dom->createElement('Grantee');
$grantee->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
if (isset($g['id'])) { // CanonicalUser (DisplayName is omitted)
$grantee->setAttribute('xsi:type', 'CanonicalUser');
$grantee->appendChild($dom->createElement('ID', $g['id']));
} elseif (isset($g['email'])) { // AmazonCustomerByEmail
$grantee->setAttribute('xsi:type', 'AmazonCustomerByEmail');
$grantee->appendChild($dom->createElement('EmailAddress', $g['email']));
} elseif ($g['type'] == 'Group') { // Group
$grantee->setAttribute('xsi:type', 'Group');
$grantee->appendChild($dom->createElement('URI', $g['uri']));
}
$grant->appendChild($grantee);
$grant->appendChild($dom->createElement('Permission', $g['permission']));
$accessControlList->appendChild($grant);
}
$accessControlPolicy->appendChild($accessControlList);
$dom->appendChild($accessControlPolicy);
$rest = new S3Request('PUT', $bucket, '');
$rest->setParameter('acl', null);
$rest->data = $dom->saveXML();
$rest->size = strlen($rest->data);
$rest->setHeader('Content-Type', 'application/xml');
$rest = $rest->getResponse();
if ($rest->error === false && $rest->code !== 200)
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
trigger_error(sprintf("S3Withprogressbar::setAccessControlPolicy({$bucket}, {$uri}): [%s] %s",
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
return true;
}
public static function getAccessControlPolicy($bucket, $uri = '') {
$rest = new S3Request('GET', $bucket, $uri);
$rest->setParameter('acl', null);
$rest = $rest->getResponse();
if ($rest->error === false && $rest->code !== 200)
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
trigger_error(sprintf("S3Withprogressbar::getAccessControlPolicy({$bucket}, {$uri}): [%s] %s",
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
$acp = array();
if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName)) {
$acp['owner'] = array(
'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->DisplayName
);
}
if (isset($rest->body->AccessControlList)) {
$acp['acl'] = array();
foreach ($rest->body->AccessControlList->Grant as $grant) {
foreach ($grant->Grantee as $grantee) {
if (isset($grantee->ID, $grantee->DisplayName)) // CanonicalUser
$acp['acl'][] = array(
'type' => 'CanonicalUser',
'id' => (string)$grantee->ID,
'name' => (string)$grantee->DisplayName,
'permission' => (string)$grant->Permission
);
elseif (isset($grantee->EmailAddress)) // AmazonCustomerByEmail
$acp['acl'][] = array(
'type' => 'AmazonCustomerByEmail',
'email' => (string)$grantee->EmailAddress,
'permission' => (string)$grant->Permission
);
elseif (isset($grantee->URI)) // Group
$acp['acl'][] = array(
'type' => 'Group',
'uri' => (string)$grantee->URI,
'permission' => (string)$grant->Permission
);
else continue;
}
}
}
return $acp;
}
public static function deleteObject($bucket = '', $uri = '') {
$rest = new S3Request('DELETE', $bucket, $uri);
$rest = $rest->getResponse();
if ($rest->error === false && $rest->code !== 204)
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
trigger_error(sprintf("S3Withprogressbar::deleteObject(): [%s] %s", $rest->error['code'], $rest->error['message']), E_USER_WARNING);
return false;
}
return true;
}
public static function __getMimeType(&$file) {
$type = false;
// Fileinfo documentation says fileinfo_open() will use the
// MAGIC env var for the magic file
if (extension_loaded('fileinfo') && isset($_ENV['MAGIC']) &&
($finfo = finfo_open(FILEINFO_MIME, $_ENV['MAGIC'])) !== false) {
if (($type = finfo_file($finfo, $file)) !== false) {
// Remove the charset and grab the last content-type
$type = explode(' ', str_replace('; charset=', ';charset=', $type));
$type = array_pop($type);
$type = explode(';', $type);
$type = array_shift($type);
}
finfo_close($finfo);
// If anyone is still using mime_content_type()
} elseif (function_exists('mime_content_type'))
$type = mime_content_type($file);
if ($type !== false && strlen($type) > 0) return $type;
// Otherwise do it the old fashioned way
static $exts = array(
'jpg' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png',
'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'ico' => 'image/x-icon',
'swf' => 'application/x-shockwave-flash', 'pdf' => 'application/pdf',
'zip' => 'application/zip', 'gz' => 'application/x-gzip',
'tar' => 'application/x-tar', 'bz' => 'application/x-bzip',
'bz2' => 'application/x-bzip2', 'txt' => 'text/plain',
'asc' => 'text/plain', 'htm' => 'text/html', 'html' => 'text/html',
'xml' => 'text/xml', 'xsl' => 'application/xsl+xml',
'ogg' => 'application/ogg', 'mp3' => 'audio/mpeg', 'wav' => 'audio/x-wav',
'avi' => 'video/x-msvideo', 'mpg' => 'video/mpeg', 'mpeg' => 'video/mpeg',
'mov' => 'video/quicktime', 'flv' => 'video/x-flv', 'php' => 'text/x-php'
);
$ext = strToLower(pathInfo($file, PATHINFO_EXTENSION));
return isset($exts[$ext]) ? $exts[$ext] : 'application/octet-stream';
}
public static function __getSignature($string) {
return 'AWS '.self::$__accessKey.':'.base64_encode(extension_loaded('hash') ?
hash_hmac('sha1', $string, self::$__secretKey, true) : pack('H*', sha1(
(str_pad(self::$__secretKey, 64, chr(0x00)) ^ (str_repeat(chr(0x5c), 64))) .
pack('H*', sha1((str_pad(self::$__secretKey, 64, chr(0x00)) ^
(str_repeat(chr(0x36), 64))) . $string)))));
}
}
final class S3Request {
private $verb, $bucket, $uri, $resource = '', $parameters = array(),
$amzHeaders = array(), $headers = array(
'Host' => '', 'Date' => '', 'Content-MD5' => '', 'Content-Type' => ''
);
public $fp = false, $size = 0, $data = false, $response;
public $uploadProgressFileName;
function __construct($verb, $bucket = '', $uri = '') {
$this->verb = $verb;
$this->bucket = strtolower($bucket);
$this->uri = $uri !== '' ? '/'.$uri : '/';
if ($this->bucket !== '') {
$this->bucket = explode('/', $this->bucket);
$this->resource = '/'.$this->bucket[0].$this->uri;
$this->headers['Host'] = $this->bucket[0].'.s3.amazonaws.com';
$this->bucket = implode('/', $this->bucket);
} else {
$this->headers['Host'] = 's3.amazonaws.com';
if (strlen($this->uri) > 1)
$this->resource = '/'.$this->bucket.$this->uri;
else $this->resource = $this->uri;
}
$this->headers['Date'] = gmdate('D, d M Y H:i:s T');
$this->response = new STDClass;
$this->response->error = false;
$this->response->body  = false;
$CI =& get_instance();
$CI->load->helper('file');
}
public function setParameter($key, $value) {
$this->parameters[$key] = $value;
}
public function setHeader($key, $value) {
$this->headers[$key] = $value;
}
public function setAmzHeader($key, $value) {
$this->amzHeaders[$key] = $value;
}
//:callback function for upload progress.
public function progressCallback_new_curl($new,$download_size, $downloaded_size, $upload_size, $uploaded_size )
{
ob_start();
static $previousProgress = 0;
if ( $upload_size == 0 )
$progress = 0;
else
$progress = round( $uploaded_size * 100 / $upload_size );
if ( $progress > $previousProgress)
{
flush();
$previousProgress = $progress;
$new_file_path = FCPATH.'upload/'.$this->uploadProgressFileName.'.txt'; // modify this line to point to the actual location of the file
write_file($new_file_path, $progress."\n");
// Check for Cancel upload text file and if exists return 1 to interrupt curl upload process.
$cancel_path=FCPATH.'upload/cancel_'.$this->uploadProgressFileName.'.txt';
if(file_exists($cancel_path)){
unlink($cancel_path);
if(file_exists($new_file_path)){
unlink($new_file_path);
}
return 1;
}
}
ob_flush();
flush();
}
public function progressCallback_old_curl($download_size, $downloaded_size, $upload_size, $uploaded_size )
{
ob_start();
static $previousProgress = 0;
if ( $upload_size == 0 )
$progress = 0;
else
$progress = round( $uploaded_size * 100 / $upload_size );
if ( $progress > $previousProgress)
{
flush();
$previousProgress = $progress;
$new_file_path = FCPATH.'upload/'.$this->uploadProgressFileName.'.txt'; // modify this line to point to the actual location of the file
write_file($new_file_path, $progress."\n");
// Check for Cancel upload text file and if exists return 1 to interrupt curl upload process.
$cancel_path=FCPATH.'upload/cancel_'.$this->uploadProgressFileName.'.txt';
if(file_exists($cancel_path)){
unlink($cancel_path);
if(file_exists($new_file_path)){
unlink($new_file_path);
}
return 1;
}
}
ob_flush();
flush();
}
public function getResponse() {
$query = '';
if (sizeof($this->parameters) > 0) {
$query = substr($this->uri, -1) !== '?' ? '?' : '&';
foreach ($this->parameters as $var => $value)
if ($value == null || $value == '') $query .= $var.'&';
else $query .= $var.'='.$value.'&';
$query = substr($query, 0, -1);
$this->uri .= $query;
if (isset($this->parameters['acl']) || !isset($this->parameters['logging']))
$this->resource .= $query;
}
$url = (extension_loaded('openssl')?'https://':'http://').$this->headers['Host'].$this->uri;
//var_dump($this->bucket, $this->uri, $this->resource, $url);
// Basic setup
$curl = curl_init();
curl_setopt($curl, CURLOPT_USERAGENT, 'S3/php');
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curl, CURLOPT_URL, $url);
//:callback function call for upload progress.
curl_setopt($curl, CURLOPT_NOPROGRESS, false);
if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 50500) {
curl_setopt($curl, CURLOPT_PROGRESSFUNCTION,  array($this, 'progressCallback_old_curl'));
} else {
curl_setopt($curl, CURLOPT_PROGRESSFUNCTION,  array($this, 'progressCallback_new_curl'));
}
// Headers
$headers = array(); $amz = array();
foreach ($this->amzHeaders as $header => $value)
if (strlen($value) > 0) $headers[] = $header.': '.$value;
foreach ($this->headers as $header => $value)
if (strlen($value) > 0) $headers[] = $header.': '.$value;
foreach ($this->amzHeaders as $header => $value)
if (strlen($value) > 0) $amz[] = strToLower($header).':'.$value;
$amz = (sizeof($amz) > 0) ? "\n".implode("\n", $amz) : '';
// Authorization string
$headers[] = 'Authorization: ' . S3Withprogressbar::__getSignature(
$this->verb."\n".
$this->headers['Content-MD5']."\n".
$this->headers['Content-Type']."\n".
$this->headers['Date'].$amz."\n".$this->resource
);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);
curl_setopt($curl, CURLOPT_WRITEFUNCTION, array(&$this, '__responseWriteCallback'));
curl_setopt($curl, CURLOPT_HEADERFUNCTION, array(&$this, '__responseHeaderCallback'));
// Request types
switch ($this->verb) {
case 'GET': break;
case 'PUT':
if ($this->fp !== false) {
curl_setopt($curl, CURLOPT_PUT, true);
curl_setopt($curl, CURLOPT_INFILE, $this->fp);
if ($this->size > 0)
curl_setopt($curl, CURLOPT_INFILESIZE, $this->size);
} elseif ($this->data !== false) {
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($curl, CURLOPT_POSTFIELDS, $this->data);
if ($this->size > 0)
curl_setopt($curl, CURLOPT_BUFFERSIZE, $this->size);
} else
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
break;
case 'HEAD':
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'HEAD');
curl_setopt($curl, CURLOPT_NOBODY, true);
break;
case 'DELETE':
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
break;
default: break;
}
// Execute, grab errors
if (curl_exec($curl))
$this->response->code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
else
$this->response->error = array(
'code' => curl_errno($curl),
'message' => curl_error($curl),
'resource' => $this->resource
);
@curl_close($curl);
// Parse body into XML
if ($this->response->error === false && isset($this->response->headers['type']) &&
$this->response->headers['type'] == 'application/xml' && isset($this->response->body)) {
$this->response->body = simplexml_load_string($this->response->body);
// Grab S3 errors
if (!in_array($this->response->code, array(200, 204)) &&
isset($this->response->body->Code, $this->response->body->Message)) {
$this->response->error = array(
'code' => (string)$this->response->body->Code,
'message' => (string)$this->response->body->Message
);
if (isset($this->response->body->Resource))
$this->response->error['resource'] = (string)$this->response->body->Resource;
unset($this->response->body);
}
}
// Clean up file resources
if ($this->fp !== false && is_resource($this->fp)) fclose($this->fp);
return $this->response;
}
private function __responseWriteCallback(&$curl, &$data) {
if ($this->response->code == 200 && $this->fp !== false)
return fwrite($this->fp, $data);
else
$this->response->body .= $data;
return strlen($data);
}
private function __responseHeaderCallback(&$curl, &$data) {
if (($strlen = strlen($data)) <= 2) return $strlen;
if (substr($data, 0, 4) == 'HTTP')
$this->response->code = (int)substr($data, 9, 3);
else {
list($header, $value) = explode(': ', trim($data));
if ($header == 'Last-Modified')
$this->response->headers['time'] = strtotime($value);
elseif ($header == 'Content-Length')
$this->response->headers['size'] = (int)$value;
elseif ($header == 'Content-Type')
$this->response->headers['type'] = $value;
elseif ($header == 'ETag')
$this->response->headers['hash'] = substr($value, 1, -1);
elseif (preg_match('/^x-amz-meta-.*$/', $header))
$this->response->headers[$header] = is_numeric($value) ? (int)$value : $value;
}
return $strlen;
}
}
?>


问:
Bash, grep between two lines with specified string
Example:

```<code>a43
test1
abc
cvb
bnm
test2
kfo
</code>```

I need all lines between test1 and test2. Normal grep does not work in this case. Do you have any propositions?

答:
You can do something like this too. Lets say you this file test.txt with content:

```<code>a43
test1
abc
cvb
bnm
test2
kfo
</code>```

You can do

cat test.txt | grep -A10 test1 | grep -B10 test2

where -A<n> is to get you n lines after your match in the file and -B<n> is to give you n lines before the match. You just have to make sure that n > number of expected lines between test1 and test2. Or you can give it large enough to reach EOF.

Result:

```<code>test1
abc
cvb
bnm
test2
</code>```

Body:
Example:

a43
test1
abc
cvb
bnm
test2
kfo

I need all lines between test1 and test2. Normal grep does not work in this case. Do you have any propositions?

Body:
You can do something like this too. Lets say you this file test.txt with content:

a43
test1
abc
cvb
bnm
test2
kfo

You can do

cat test.txt | grep -A10 test1 | grep -B10 test2

where -A<n> is to get you n lines after your match in the file and -B<n> is to give you n lines before the match. You just have to make sure that n > number of expected lines between test1 and test2. Or you can give it large enough to reach EOF.

Result:

test1
abc
cvb
bnm
test2


问:
native element not defined when ngSwitch condition in canvas element
I am working with chart.js in my ionic 2 application if i implement canvas element with out ngSwitch condition for rendering it works fine but when i use condition i got error with native element not defined so canvas element not rendered because canvas element not ready at the time of subscribe chart data. how can i solve this.</p>

```<code>  @ViewChild('todayChart') todayChart;
 @ViewChild('yesterdayChart') yesterdayChart;

ionViewWillEnter() {

     this.homeauth.todaychart().subscribe((table) => {
         var labels = [], datay = [], datum = [], timestamp = [];
         for (var i = 0; i <= table.length - 1; i++) {
             datum.push(table[i].chartdate);
             labels.push(table[i].z10s3);
             datay.push(table[i].z10s6);
             timestamp.push(table[i].timestamp);
         }

         this.heutechart = new Chart(this.todayChart.nativeElement, {
             type: 'line',
             data: {
                 xLabels: labels,
                 datasets: [
                     {
                         label: 'G.Oil', fill: true, lineTension: 0.1, backgroundColor: "rgba(75,192,192,0.4)", borderColor: "rgba(75,192,192,1)",
                         pointHoverBorderWidth: 2, pointRadius: 1, pointHitRadius: 10, data: datay, spanGaps: false,
                     }
                 ],

             },
         });
     });

     this.homeauth.yesterdaychart().subscribe((table) => {
         var labels = [], datay = [], datum = [];
         for (var i = 0; i <= table.length - 1; i++) {
             datum.push(table[i].chartdate);
             labels.push(table[i].z10s3);
             datay.push(table[i].z10s6);
         }

         this.vortagschart = new Chart(this.yesterdayChart.nativeElement, {

             type: 'line',
             data: {
                 xLabels: labels,
                 datasets: [
                     {
                         label: 'G.Oil', fill: true, lineTension: 0.1, backgroundColor: "rgba(75,192,192,0.4)", borderColor: "rgba(75,192,192,1)",
                         pointHoverBorderWidth: 2, pointRadius: 1, pointHitRadius: 10, data: datay, spanGaps: false,
                     }
                 ],

             }
         });
     });

 }

html:

 <ion-segment [(ngModel)]="category">
    <ion-segment-button value="today"> 24h </ion-segment-button>
    <ion-segment-button value="yesterday"> 48h </ion-segment-button>
</ion-segment>

<div [ngSwitch]="category">
  <div *ngSwitchCase="'today'">
    <canvas #yesterdayChart> </canvas>
  </div>
</div>

<div [ngSwitch]="category">
  <div *ngSwitchCase="'yesterday'">
    <canvas #todayChart></canvas>
  </div>
</div>
</code>```

答:
you dont have to use ng-switch for each case.

It should be like so:

```<code><div [ngSwitch]="category">
  <div *ngSwitchCase="'today'"> <!-- case 1 -->
    <canvas #yesterdayChart> </canvas>
  </div>
  <div *ngSwitchCase="'yesterday'">
    <canvas #todayChart></canvas> <!-- case 2 -->
  </div>
</div>
</code>```

Add if conditions in the component since only one of these elements will be present in the DOM.

```<code>if(this.todayChart){
  this.heutechart = new Chart(this.todayChart.nativeElement, {
             type: 'line',
             data: {
                 xLabels: labels,
                 datasets: [
                     {
                         label: 'G.Oil', fill: true, lineTension: 0.1, backgroundColor: "rgba(75,192,192,0.4)", borderColor: "rgba(75,192,192,1)",
                         pointHoverBorderWidth: 2, pointRadius: 1, pointHitRadius: 10, data: datay, spanGaps: false,
                     }
                 ],

             },
         });
     });
  }
 //Similarly for yesterdayChart
</code>```

Body:
I am working with chart.js in my ionic 2 application if i implement canvas element with out ngSwitch condition for rendering it works fine but when i use condition i got error with native element not defined so canvas element not rendered because canvas element not ready at the time of subscribe chart data. how can i solve this.

  @ViewChild('todayChart') todayChart;
 @ViewChild('yesterdayChart') yesterdayChart;

ionViewWillEnter() {

     this.homeauth.todaychart().subscribe((table) => {
         var labels = [], datay = [], datum = [], timestamp = [];
         for (var i = 0; i <= table.length - 1; i++) {
             datum.push(table[i].chartdate);
             labels.push(table[i].z10s3);
             datay.push(table[i].z10s6);
             timestamp.push(table[i].timestamp);
         }

         this.heutechart = new Chart(this.todayChart.nativeElement, {
             type: 'line',
             data: {
                 xLabels: labels,
                 datasets: [
                     {
                         label: 'G.Oil', fill: true, lineTension: 0.1, backgroundColor: "rgba(75,192,192,0.4)", borderColor: "rgba(75,192,192,1)",
                         pointHoverBorderWidth: 2, pointRadius: 1, pointHitRadius: 10, data: datay, spanGaps: false,
                     }
                 ],

             },
         });
     });

     this.homeauth.yesterdaychart().subscribe((table) => {
         var labels = [], datay = [], datum = [];
         for (var i = 0; i <= table.length - 1; i++) {
             datum.push(table[i].chartdate);
             labels.push(table[i].z10s3);
             datay.push(table[i].z10s6);
         }

         this.vortagschart = new Chart(this.yesterdayChart.nativeElement, {

             type: 'line',
             data: {
                 xLabels: labels,
                 datasets: [
                     {
                         label: 'G.Oil', fill: true, lineTension: 0.1, backgroundColor: "rgba(75,192,192,0.4)", borderColor: "rgba(75,192,192,1)",
                         pointHoverBorderWidth: 2, pointRadius: 1, pointHitRadius: 10, data: datay, spanGaps: false,
                     }
                 ],

             }
         });
     });

 }

html:

 <ion-segment [(ngModel)]="category">
    <ion-segment-button value="today"> 24h </ion-segment-button>
    <ion-segment-button value="yesterday"> 48h </ion-segment-button>
</ion-segment>

    <canvas #yesterdayChart> </canvas>

    <canvas #todayChart></canvas>

Body:
you dont have to use ng-switch for each case.

It should be like so:

<div [ngSwitch]="category">
  <div *ngSwitchCase="'today'"> <!-- case 1 -->
    <canvas #yesterdayChart> </canvas>
  </div>
  <div *ngSwitchCase="'yesterday'">
    <canvas #todayChart></canvas> <!-- case 2 -->
  </div>
</div>

Add if conditions in the component since only one of these elements will be present in the DOM.

if(this.todayChart){
  this.heutechart = new Chart(this.todayChart.nativeElement, {
             type: 'line',
             data: {
                 xLabels: labels,
                 datasets: [
                     {
                         label: 'G.Oil', fill: true, lineTension: 0.1, backgroundColor: "rgba(75,192,192,0.4)", borderColor: "rgba(75,192,192,1)",
                         pointHoverBorderWidth: 2, pointRadius: 1, pointHitRadius: 10, data: datay, spanGaps: false,
                     }
                 ],

             },
         });
     });
  }
 //Similarly for yesterdayChart


问:
How to bind properties to another UserControl?
ItemsControl is associated with a collection of objects. As a template, 2 other UserControl are used, which need to associate properties with the properties of the collection objects. I do this:

```<code><local:DayControl Date="{Binding Date}"/>
<local:IntervalControl Intervals="{Binding Intervals}"/>
</code>```

But it does not work! We have to do this:

```<code><TextBlock x:Name="date" Text="{Binding Date}" Visibility="Hidden"/>
<ItemsControl x:Name="items" ItemsSource="{Binding Intervals}"/>
<local:DayControl Date="{Binding ElementName=date, Path=Text}"/>
<local:IntervalControl Intervals="{Binding ElementName=items, Path=ItemsSource}"/>
</code>```

How to do it right?

答:
Check data types for Binding values and what your controls expect.

If you want to databind ... properties that have incompatible types, you need a piece of code in between, that converts the value from source to target type and back.

It seems you need a converter in your code-behind here and at the moment you employ implicit type conversion through TextBlock (to String) and through ItemsControl (to IEnumerable?).

Body:
ItemsControl is associated with a collection of objects. As a template, 2 other UserControl are used, which need to associate properties with the properties of the collection objects. I do this:

<local:DayControl Date="{Binding Date}"/>
<local:IntervalControl Intervals="{Binding Intervals}"/>

But it does not work! We have to do this:

<TextBlock x:Name="date" Text="{Binding Date}" Visibility="Hidden"/>
<ItemsControl x:Name="items" ItemsSource="{Binding Intervals}"/>
<local:DayControl Date="{Binding ElementName=date, Path=Text}"/>
<local:IntervalControl Intervals="{Binding ElementName=items, Path=ItemsSource}"/>

How to do it right?